/*
Copyright 2013-present Barefoot Networks, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// This autogenerated skeleton file illustrates how to build a server.
// You should copy it to another filename to avoid overwriting it.

#include <cstddef>
#include <cstdint>
#include <cstring>
#include <ctime>

#include <iostream>
#include <sstream>
#include <fstream>

#include <string>
#include <vector>

#include <iomanip>

#include <iostream>
#include <string>
#include "switch_sai_rpc.h"
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>
#include <arpa/inet.h>

#include <inttypes.h>

#ifdef __cplusplus
extern "C" {
#endif
#include <sai.h>
#ifdef __cplusplus
}
#endif

#include <saifdb.h>
#include <saivlan.h>
#include <sairouterinterface.h>
#include <sairoute.h>
#include <saiswitch.h>
#include <saimirror.h>
#include <saistatus.h>

#include "arpa/inet.h"

#define SAI_THRIFT_LOG_DBG(msg, ...) sai_thrift_timestamp_print(); \
    printf("SAI THRIFT DEBUG: %s(): " msg "\n", __FUNCTION__, ##__VA_ARGS__);

#define SAI_THRIFT_LOG_ERR(msg, ...) sai_thrift_timestamp_print(); \
    printf("SAI THRIFT ERROR: %s(): " msg "\n", __FUNCTION__, ##__VA_ARGS__);

#define SAI_THRIFT_FUNC_LOG() SAI_THRIFT_LOG_DBG("Called.")

#define CNT_UNSUPPORT 10

#define DUMP_FILE_NAME_LEN 51

using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;

using boost::shared_ptr;

using namespace ::switch_sai;
#define SAI_CPU_PACKET_MAX_ATTR_COUNT 6
extern sai_attribute_t packet_rx_attr[SAI_CPU_PACKET_MAX_ATTR_COUNT];
extern int packet_rx_attr_count;
extern int packets_rx_count;
extern sai_object_id_t gSwitchId;

typedef std::vector<sai_thrift_attribute_t> std_sai_thrift_attr_vctr_t;

class switch_sai_rpcHandler : virtual public switch_sai_rpcIf {
public:
    switch_sai_rpcHandler() noexcept
    {
        // Your initialization goes here
    }

    inline void sai_thrift_timestamp_print() const noexcept
    {
        const auto ltime = std::time(nullptr);
        const auto tm = std::localtime(&ltime);

        std::printf("%02d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec);
    }

    template<typename T>
    inline void sai_thrift_alloc_array(T* &arr, const std::size_t &size) const noexcept
    { arr = new (std::nothrow) T[size]; }

    template<typename T>
    inline void sai_thrift_free_array(T* &arr) const noexcept
    { delete[] arr; arr = nullptr; }

  unsigned int sai_thrift_string_to_mac(const std::string s, unsigned char *m) {
      unsigned int i, j=0;
      memset(m, 0, 6);
      for(i=0;i<s.size();i++) {
          char let = s.c_str()[i];
          if (let >= '0' && let <= '9') {
              m[j/2] = (m[j/2] << 4) + (let - '0'); j++;
          } else if (let >= 'a' && let <= 'f') {
              m[j/2] = (m[j/2] << 4) + (let - 'a'+10); j++;
          } else if (let >= 'A' && let <= 'F') {
              m[j/2] = (m[j/2] << 4) + (let - 'A'+10); j++;
          }
      }
      return (j == 12);
  }

  std::string sai_thrift_mac_to_string(const unsigned char *m) {
      unsigned int i=0;
      std::string mac_str;
      char mac[18]={'0','0',':',
                      '0','0',':',
                      '0','0',':',
                      '0','0',':',
                      '0','0',':',
                      '0','0','\0'};

      for (i = 0; i < 6; i++)
      {
          sprintf(&mac[i*3], "%02x", m[i]);
          mac[i*3 + 2] = ':';
      }
      mac[17] = '\0';
      mac_str = mac;

      return mac_str;
  }

  void sai_thrift_string_to_v4_ip(const std::string s, unsigned int *m) {
      unsigned char r=0;
      unsigned int i;
      *m = 0;
      for(i=0;i<s.size();i++) {
          char let = s.c_str()[i];
          if (let >= '0' && let <= '9') {
              r = (r * 10) + (let - '0');
          } else {
              *m = (*m << 8) | r;
              r=0;
          }
      }
      *m = (*m << 8) | (r & 0xFF);
      *m = htonl(*m);
      return;
  }

  std::string sai_thrift_v4_ip_to_string(const unsigned int m) {
      std::string ip_str;
      char ipv4_str[44];
      inet_ntop(AF_INET, &m, ipv4_str, 44);
      ip_str = ipv4_str;
      return ip_str;
  }

  std::string sai_thrift_v6_ip_to_string(const unsigned char *v6_ip) {
      unsigned int ip6[4];
      std :: string ip_str;
      char ipv6_str[44];
      ip6[0] = htonl(*((unsigned int *)v6_ip));
	  ip6[1] = htonl(*((unsigned int *)v6_ip + 1));
	  ip6[2] = htonl(*((unsigned int *)v6_ip + 2));
	  ip6[3] = htonl(*((unsigned int *)v6_ip + 3));
      inet_ntop(AF_INET6, &ip6, ipv6_str, 44);
      ip_str = ipv6_str;
      return ip_str;
  }

  void sai_thrift_string_to_v6_ip(const std::string s, unsigned char *v6_ip) {
      const char *v6_str = s.c_str();
      inet_pton(AF_INET6, v6_str, v6_ip);
      return;
  }


    inline void sai_thrift_alloc_attr(sai_attribute_t* &attr, const sai_uint32_t &size) const noexcept
    { attr = new (std::nothrow) sai_attribute_t[size]; }

    inline void sai_thrift_free_attr(sai_attribute_t* &attr) const noexcept
    { delete[] attr; attr = nullptr; }

  void sai_thrift_parse_object_id_list(const std::vector<sai_thrift_object_id_t> & thrift_object_id_list, sai_object_id_t *object_id_list) {
      std::vector<sai_thrift_object_id_t>::const_iterator it = thrift_object_id_list.begin();
      for(uint32_t i = 0; i < thrift_object_id_list.size(); i++, it++) {
          object_id_list[i] = (sai_object_id_t)*it;
      }
  }

  void sai_thrift_parse_ip_address(const sai_thrift_ip_address_t &thrift_ip_address, sai_ip_address_t *ip_address) {
      ip_address->addr_family = (sai_ip_addr_family_t) thrift_ip_address.addr_family;
      if ((sai_ip_addr_family_t)thrift_ip_address.addr_family == SAI_IP_ADDR_FAMILY_IPV4) {
          sai_thrift_string_to_v4_ip(thrift_ip_address.addr.ip4, &ip_address->addr.ip4);
      } else {
          sai_thrift_string_to_v6_ip(thrift_ip_address.addr.ip6, ip_address->addr.ip6);
      }
  }

  void sai_thrift_parse_ip_prefix(const sai_thrift_ip_prefix_t &thrift_ip_prefix, sai_ip_prefix_t *ip_prefix) {
      ip_prefix->addr_family = (sai_ip_addr_family_t) thrift_ip_prefix.addr_family;
      if ((sai_ip_addr_family_t)thrift_ip_prefix.addr_family == SAI_IP_ADDR_FAMILY_IPV4) {
          sai_thrift_string_to_v4_ip(thrift_ip_prefix.addr.ip4, &ip_prefix->addr.ip4);
          sai_thrift_string_to_v4_ip(thrift_ip_prefix.mask.ip4, &ip_prefix->mask.ip4);
      } else {
          sai_thrift_string_to_v6_ip(thrift_ip_prefix.addr.ip6, ip_prefix->addr.ip6);
          sai_thrift_string_to_v6_ip(thrift_ip_prefix.mask.ip6, ip_prefix->mask.ip6);
      }
  }

  void sai_thrift_parse_attribute_ids(const std::vector<int32_t> &thrift_attr_id_list, sai_attribute_t *attr_list) {
      std::vector<int32_t>::const_iterator it = thrift_attr_id_list.begin();
      for(uint32_t i = 0; i < thrift_attr_id_list.size(); i++, it++) {
          attr_list[i].id = (int32_t) *it;
      }
  }

  sai_attribute_t *sai_thrift_attribute_list_to_sai(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_attribute_t *sai_attrs;

      sai_attrs = (sai_attribute_t *) calloc(thrift_attr_list.size(), sizeof(sai_attribute_t));
      if (!sai_attrs) {
          SAI_THRIFT_LOG_ERR("failed to allocate sai attibutes list");
          return NULL;
      }

      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          sai_thrift_attribute_t & thrift_attr = (sai_thrift_attribute_t &) *it;
          sai_attrs[i].id = thrift_attr.id;
          sai_attrs[i].value.oid = thrift_attr.value.oid;
      }

      return sai_attrs;
  }

  void sai_attributes_to_sai_thrift_list(sai_attribute_t *sai_attrs, uint32_t count, std::vector<sai_thrift_attribute_t> & thrift_attr_list) {

      for (uint32_t i = 0; i < count; i++) {
          sai_thrift_attribute_t thrift_attr;

          thrift_attr.id        = sai_attrs[i].id;
          thrift_attr.value.oid = sai_attrs[i].value.oid;

          thrift_attr_list.push_back(thrift_attr);
      }
  }

  void sai_attributes_booldata_to_sai_thrift_list(sai_attribute_t *sai_attrs, uint32_t count, std::vector<sai_thrift_attribute_t> & thrift_attr_list) {

      for (uint32_t i = 0; i < count; i++) {
          sai_thrift_attribute_t thrift_attr;

          thrift_attr.id        = sai_attrs[i].id;
          thrift_attr.value.booldata = sai_attrs[i].value.booldata;

          thrift_attr_list.push_back(thrift_attr);
      }
  }

  void sai_attributes_s32_to_sai_thrift_list(sai_attribute_t *sai_attrs, uint32_t count, std::vector<sai_thrift_attribute_t> & thrift_attr_list) {

      for (uint32_t i = 0; i < count; i++) {
          sai_thrift_attribute_t thrift_attr;

          thrift_attr.id        = sai_attrs[i].id;
          thrift_attr.value.s32 = sai_attrs[i].value.s32;

          thrift_attr_list.push_back(thrift_attr);
      }
  }

  void sai_attributes_u32_to_sai_thrift_list(sai_attribute_t *sai_attrs, uint32_t count, std::vector<sai_thrift_attribute_t> & thrift_attr_list) {

      for (uint32_t i = 0; i < count; i++) {
          sai_thrift_attribute_t thrift_attr;

          thrift_attr.id        = sai_attrs[i].id;
          thrift_attr.value.u32 = sai_attrs[i].value.u32;

          thrift_attr_list.push_back(thrift_attr);
      }
  }

  void sai_thrift_parse_fdb_entry(const sai_thrift_fdb_entry_t &thrift_fdb_entry, sai_fdb_entry_t *fdb_entry) {
      fdb_entry->bv_id = (sai_object_id_t) thrift_fdb_entry.bv_id;
      fdb_entry->switch_id = gSwitchId;
      sai_thrift_string_to_mac(thrift_fdb_entry.mac_address, fdb_entry->mac_address);
  }

  void sai_thrift_parse_route_entry(const sai_thrift_route_entry_t &thrift_route_entry, sai_route_entry_t *route_entry) {
      route_entry->switch_id = gSwitchId;
      route_entry->vr_id = (sai_object_id_t) thrift_route_entry.vr_id;
      sai_thrift_parse_ip_prefix(thrift_route_entry.destination, &route_entry->destination);
  }

  void sai_thrift_parse_neighbor_entry(const sai_thrift_neighbor_entry_t &thrift_neighbor_entry, sai_neighbor_entry_t *neighbor_entry) {
      neighbor_entry->switch_id = gSwitchId;
      neighbor_entry->rif_id = (sai_object_id_t) thrift_neighbor_entry.rif_id;
      sai_thrift_parse_ip_address(thrift_neighbor_entry.ip_address, &neighbor_entry->ip_address);
  }

  void sai_thrift_parse_ipmc_entry(const sai_thrift_ipmc_entry_t &thrift_ipmc_entry, sai_ipmc_entry_t *ipmc_entry) {
      ipmc_entry->switch_id = gSwitchId;
      ipmc_entry->vr_id = (sai_object_id_t) thrift_ipmc_entry.vr_id;
      ipmc_entry->type = (sai_ipmc_entry_type_t) thrift_ipmc_entry.type;
      sai_thrift_parse_ip_address(thrift_ipmc_entry.source, &ipmc_entry->source);
      sai_thrift_parse_ip_address(thrift_ipmc_entry.destination, &ipmc_entry->destination);
  }

  void sai_thrift_parse_l2mc_entry(const sai_thrift_l2mc_entry_t &thrift_l2mc_entry, sai_l2mc_entry_t *l2mc_entry) {
      l2mc_entry->switch_id = gSwitchId;
      l2mc_entry->bv_id = (sai_object_id_t) thrift_l2mc_entry.bv_id;
      l2mc_entry->type = (sai_l2mc_entry_type_t) thrift_l2mc_entry.type;
      sai_thrift_parse_ip_address(thrift_l2mc_entry.source, &l2mc_entry->source);
      sai_thrift_parse_ip_address(thrift_l2mc_entry.destination, &l2mc_entry->destination);
  }

  void sai_thrift_parse_mcast_fdb_entry(const sai_thrift_mcast_fdb_entry_t &thrift_mcast_fdb_entry, sai_mcast_fdb_entry_t *mcast_fdb_entry) {
      mcast_fdb_entry->switch_id = gSwitchId;
      mcast_fdb_entry->bv_id = (sai_object_id_t) thrift_mcast_fdb_entry.bv_id;
      sai_thrift_string_to_mac(thrift_mcast_fdb_entry.mac_address, mcast_fdb_entry->mac_address);
  }

  void sai_thrift_parser_inseg_entry(const sai_thrift_inseg_entry_t &thrift_mpls_entry, sai_inseg_entry_t *mpls_entry) {
      mpls_entry->switch_id = gSwitchId;
      mpls_entry->label = (sai_label_id_t)thrift_mpls_entry.label;
  }

  void sai_thrift_parse_port_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list, sai_object_id_t **buffer_profile_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;

      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
              case SAI_PORT_ATTR_ADMIN_STATE:
              case SAI_PORT_ATTR_UPDATE_DSCP:
			  case SAI_PORT_ATTR_PKT_TX_ENABLE:
                  attr_list[i].value.booldata = attribute.value.booldata;
                  break;
              case SAI_PORT_ATTR_PORT_VLAN_ID:
                  attr_list[i].value.u16 = attribute.value.u16;
                  break;
              case SAI_PORT_ATTR_PRIORITY_FLOW_CONTROL:
              case SAI_PORT_ATTR_QOS_DEFAULT_TC:
                  attr_list[i].value.u8 = attribute.value.u8;
                  break;
              case SAI_PORT_ATTR_QOS_INGRESS_BUFFER_PROFILE_LIST:
              case SAI_PORT_ATTR_QOS_EGRESS_BUFFER_PROFILE_LIST:
                  {
                  *buffer_profile_list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * attribute.value.objlist.count);
                  std::vector<sai_thrift_object_id_t>::const_iterator it2 = attribute.value.objlist.object_id_list.begin();
                  for (uint32_t j = 0; j < attribute.value.objlist.object_id_list.size(); j++, *it2++) {
                      (*buffer_profile_list)[j] = (sai_object_id_t) *it2;
                  }
                  attr_list[i].value.objlist.count = attribute.value.objlist.count;
                  attr_list[i].value.objlist.list = *buffer_profile_list;
                  break;
              }
              case SAI_PORT_ATTR_INGRESS_MIRROR_SESSION:
              case SAI_PORT_ATTR_EGRESS_MIRROR_SESSION:
			  case SAI_PORT_ATTR_EGRESS_BLOCK_PORT_LIST:
              {
                  *buffer_profile_list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * attribute.value.objlist.count);
                  std::vector<sai_thrift_object_id_t>::const_iterator it2 = attribute.value.objlist.object_id_list.begin();
                  for (uint32_t j = 0; j < attribute.value.objlist.object_id_list.size(); j++, *it2++) {
                      (*buffer_profile_list)[j] = (sai_object_id_t) *it2;
                  }
                  attr_list[i].value.objlist.count = attribute.value.objlist.count;
                  attr_list[i].value.objlist.list=*buffer_profile_list;
                  break;
              }
              case SAI_PORT_ATTR_QOS_SCHEDULER_PROFILE_ID:
              case SAI_PORT_ATTR_QOS_DOT1P_TO_TC_MAP:
              case SAI_PORT_ATTR_QOS_DOT1P_TO_COLOR_MAP:
              case SAI_PORT_ATTR_QOS_DSCP_TO_TC_MAP:
              case SAI_PORT_ATTR_QOS_DSCP_TO_COLOR_MAP:
              case SAI_PORT_ATTR_QOS_TC_TO_QUEUE_MAP:
              case SAI_PORT_ATTR_QOS_TC_AND_COLOR_TO_DOT1P_MAP:
              case SAI_PORT_ATTR_QOS_TC_AND_COLOR_TO_DSCP_MAP:
              case SAI_PORT_ATTR_QOS_TC_TO_PRIORITY_GROUP_MAP:
              case SAI_PORT_ATTR_QOS_PFC_PRIORITY_TO_PRIORITY_GROUP_MAP:
              case SAI_PORT_ATTR_QOS_PFC_PRIORITY_TO_QUEUE_MAP:
              case SAI_PORT_ATTR_INGRESS_ACL:
              case SAI_PORT_ATTR_POLICER_ID:
              case SAI_PORT_ATTR_FLOOD_STORM_CONTROL_POLICER_ID:
              case SAI_PORT_ATTR_BROADCAST_STORM_CONTROL_POLICER_ID:
              case SAI_PORT_ATTR_MULTICAST_STORM_CONTROL_POLICER_ID:
              case SAI_PORT_ATTR_INGRESS_SAMPLEPACKET_ENABLE:
              case SAI_PORT_ATTR_EGRESS_SAMPLEPACKET_ENABLE:
              attr_list[i].value.oid = attribute.value.oid;
              break;
              case SAI_PORT_ATTR_MTU:
              attr_list[i].value.u32 = attribute.value.u32;
              break;
              case SAI_PORT_ATTR_META_DATA:
              attr_list[i].value.u32 = attribute.value.u32;
              break;
              default:
                  break;
          }
      }
  }

  void sai_thrift_parse_fdb_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
              case SAI_FDB_ENTRY_ATTR_TYPE:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
              case SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;
              case SAI_FDB_ENTRY_ATTR_PACKET_ACTION:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
              case SAI_FDB_ENTRY_ATTR_ENDPOINT_IP:
                  sai_thrift_parse_ip_address(attribute.value.ipaddr, &attr_list[i].value.ipaddr);
                  break;
              case SAI_FDB_ENTRY_ATTR_META_DATA:
                  attr_list[i].value.u32 = attribute.value.u32;
                  break;
              default:
                  break;
          }
      }
  }

  void sai_thrift_parse_fdb_flush_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
              case SAI_FDB_FLUSH_ATTR_BRIDGE_PORT_ID:
                  attr_list[i].value.oid = (sai_object_id_t) attribute.value.oid;
                  break;
              case SAI_FDB_FLUSH_ATTR_BV_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;
              case SAI_FDB_FLUSH_ATTR_ENTRY_TYPE:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
          }
      }
  }

  void sai_thrift_parse_vr_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
              case SAI_VIRTUAL_ROUTER_ATTR_ADMIN_V4_STATE:
              case SAI_VIRTUAL_ROUTER_ATTR_ADMIN_V6_STATE:
                  attr_list[i].value.booldata = attribute.value.booldata;
                  break;
              case SAI_VIRTUAL_ROUTER_ATTR_SRC_MAC_ADDRESS:
                  sai_thrift_string_to_mac(attribute.value.mac, attr_list[i].value.mac);
                  break;
          }
      }
  }

  void sai_thrift_parse_route_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
              case SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;
              case SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
              case SAI_ROUTE_ENTRY_ATTR_META_DATA:
                  attr_list[i].value.u32 = attribute.value.u32;
                  break;
              default:
                  break;
          }
      }
  }

  void sai_thrift_parse_router_interface_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
              case SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID:
              case SAI_ROUTER_INTERFACE_ATTR_PORT_ID:
              case SAI_ROUTER_INTERFACE_ATTR_VLAN_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;
              case SAI_ROUTER_INTERFACE_ATTR_TYPE:
              case SAI_ROUTER_INTERFACE_ATTR_NEIGHBOR_MISS_PACKET_ACTION:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
              case SAI_ROUTER_INTERFACE_ATTR_MTU:
                  attr_list[i].value.u32 = attribute.value.u32;
                  break;
              case SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS:
                  sai_thrift_string_to_mac(attribute.value.mac, attr_list[i].value.mac);
                  break;
              case SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_STATE:
              case SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_STATE:
              case SAI_ROUTER_INTERFACE_ATTR_V4_MCAST_ENABLE:
              case SAI_ROUTER_INTERFACE_ATTR_V6_MCAST_ENABLE:
			  case SAI_ROUTER_INTERFACE_ATTR_IS_VIRTUAL:
                  attr_list[i].value.booldata = attribute.value.booldata;
                  break;
              case SAI_ROUTER_INTERFACE_ATTR_INGRESS_ACL:
              case SAI_ROUTER_INTERFACE_ATTR_EGRESS_ACL:
                  attr_list[i].value.oid = attribute.value.oid;
              default:
                  break;
          }
      }
  }

  void sai_thrift_parse_next_hop_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list, sai_uint32_t **buffer_profile_list1) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
              case SAI_NEXT_HOP_ATTR_TYPE:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
              case SAI_NEXT_HOP_ATTR_IP:
                  sai_thrift_parse_ip_address(attribute.value.ipaddr, &attr_list[i].value.ipaddr);
                  break;
              case SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID:
			  case SAI_NEXT_HOP_ATTR_TUNNEL_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;
			  case SAI_NEXT_HOP_ATTR_LABELSTACK:
                  {
                      *buffer_profile_list1 = (uint32_t *) malloc(sizeof(uint32_t) * attribute.value.u32list.count);
                      std::vector<sai_int32_t>::const_iterator it2 = attribute.value.u32list.u32list.begin();
                      for (uint32_t j = 0; j < attribute.value.u32list.u32list.size(); j++, *it2++)
                      {
                          (*buffer_profile_list1)[j] = (sai_uint32_t) *it2;
                      }
                      attr_list[i].value.u32list.count = attribute.value.u32list.count;
                      attr_list[i].value.u32list.list = *buffer_profile_list1;
                      break;
                  }
			  default:
			  	  break;
          }
      }
  }

  void sai_thrift_parse_lag_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it1 = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it1++) {
          attribute = (sai_thrift_attribute_t)*it1;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
              case SAI_LAG_ATTR_PORT_VLAN_ID:
                  attr_list[i].value.u16 = attribute.value.u16;
                  break;
                  case SAI_LAG_ATTR_DROP_UNTAGGED:
                  attr_list[i].value.booldata = attribute.value.booldata;
                  break;
                  case SAI_LAG_ATTR_DROP_TAGGED:
                  attr_list[i].value.booldata = attribute.value.booldata;
                  break;
				  case SAI_LAG_ATTR_INGRESS_ACL:
				  attr_list[i].value.oid = attribute.value.oid;
				  break;
              default:
                  SAI_THRIFT_LOG_ERR("Failed to parse attribute.");
                  break;
          }
      }
  }

  void sai_thrift_parse_lag_member_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it1 = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it1++) {
          attribute = (sai_thrift_attribute_t)*it1;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
              case SAI_LAG_MEMBER_ATTR_LAG_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;
              case SAI_LAG_MEMBER_ATTR_PORT_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;
              case SAI_LAG_MEMBER_ATTR_EGRESS_DISABLE:
                attr_list[i].value.booldata = attribute.value.booldata;
                  break;
              case SAI_LAG_MEMBER_ATTR_INGRESS_DISABLE:
                attr_list[i].value.booldata = attribute.value.booldata;
                  break;
          }
      }
  }

  void sai_thrift_parse_stp_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list, sai_vlan_id_t **vlan_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it1 = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it1++) {
          attribute = (sai_thrift_attribute_t)*it1;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
              case SAI_STP_ATTR_VLAN_LIST:
                  *vlan_list = (sai_vlan_id_t *) malloc(sizeof(sai_vlan_id_t) * attribute.value.vlanlist.vlan_count);
                  std::vector<sai_thrift_vlan_id_t>::const_iterator it2 = attribute.value.vlanlist.vlan_list.begin();
                  for (uint32_t j = 0; j < attribute.value.vlanlist.vlan_list.size(); j++, *it2++) {
                      *vlan_list[j] = (sai_vlan_id_t) *it2;
                  }
                  attr_list[i].value.vlanlist.count = attribute.value.vlanlist.vlan_count;
                  attr_list[i].value.vlanlist.list = *vlan_list;
                  break;
          }
      }
  }

  void sai_thrift_parse_neighbor_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it1 = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it1++) {
          attribute = (sai_thrift_attribute_t)*it1;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
              case SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS:
                  sai_thrift_string_to_mac(attribute.value.mac, attr_list[i].value.mac);
                  break;
              case SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
              case SAI_NEIGHBOR_ENTRY_ATTR_NO_HOST_ROUTE:
                  attr_list[i].value.booldata = attribute.value.booldata;
                  break;
          }
      }
  }

  void sai_thrift_parse_hostif_attributes(sai_attribute_t *attr_list, const std::vector<sai_thrift_attribute_t> &thrift_attr_list) const noexcept
  {
      if (attr_list == nullptr || thrift_attr_list.empty())
      { SAI_THRIFT_LOG_ERR("Invalid input arguments."); return; }

      std::vector<sai_thrift_attribute_t>::const_iterator cit = thrift_attr_list.begin();
      for (sai_size_t i = 0; i < thrift_attr_list.size(); i++, cit++)
      {
          sai_thrift_attribute_t attribute = *cit;
          attr_list[i].id = attribute.id;

          switch (attribute.id)
          {
              case SAI_HOSTIF_ATTR_TYPE:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;

              case SAI_HOSTIF_ATTR_OBJ_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;

              case SAI_HOSTIF_ATTR_NAME:
                  std::memcpy(attr_list[i].value.chardata, attribute.value.chardata.c_str(), SAI_HOSTIF_NAME_SIZE);
                  break;

		      case SAI_HOSTIF_ATTR_OPER_STATUS:
			  	  attr_list[i].value.booldata = attribute.value.booldata;
				  break;

              default:
                  SAI_THRIFT_LOG_ERR("Failed to parse attribute.");
                  break;
          }
      }
  }

  void sai_thrift_parse_hostif_table_entry_attributes(sai_attribute_t *attr_list, const std::vector<sai_thrift_attribute_t> &thrift_attr_list) const noexcept
  {
      if (attr_list == nullptr || thrift_attr_list.empty())
      { SAI_THRIFT_LOG_ERR("Invalid input arguments."); return; }

      std::vector<sai_thrift_attribute_t>::const_iterator cit = thrift_attr_list.begin();
      for (sai_size_t i = 0; i < thrift_attr_list.size(); i++, cit++)
      {
          sai_thrift_attribute_t attribute = *cit;
          attr_list[i].id = attribute.id;

          switch (attribute.id)
          {
              case SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;

              case SAI_HOSTIF_TABLE_ENTRY_ATTR_OBJ_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;

              case SAI_HOSTIF_TABLE_ENTRY_ATTR_TRAP_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;

              case SAI_HOSTIF_TABLE_ENTRY_ATTR_CHANNEL_TYPE:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;

              default:
                  SAI_THRIFT_LOG_ERR("Failed to parse attribute.");
                  break;
          }
      }
  }

  void sai_thrift_parse_hostif_trap_group_attributes(sai_attribute_t *attr_list, const std::vector<sai_thrift_attribute_t> &thrift_attr_list) const noexcept
  {
      if (attr_list == nullptr || thrift_attr_list.empty())
      { SAI_THRIFT_LOG_ERR("Invalid input arguments."); return; }

      std::vector<sai_thrift_attribute_t>::const_iterator cit = thrift_attr_list.begin();

      for (sai_size_t i = 0; i < thrift_attr_list.size(); i++, cit++)
      {
          sai_thrift_attribute_t attribute = *cit;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
              case SAI_HOSTIF_TRAP_GROUP_ATTR_ADMIN_STATE:
                  attr_list[i].value.booldata = attribute.value.booldata;
                  break;
              case SAI_HOSTIF_TRAP_GROUP_ATTR_QUEUE:
                  attr_list[i].value.u32 = attribute.value.u32;
                  break;
              case SAI_HOSTIF_TRAP_GROUP_ATTR_POLICER:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;
              default:
                  SAI_THRIFT_LOG_ERR("Failed to parse attribute.");
                  break;
          }
      }
  }

  void sai_thrift_parse_hostif_trap_attributes(sai_attribute_t *attr_list, const std::vector<sai_thrift_attribute_t> &thrift_attr_list) const noexcept
  {
      if (attr_list == nullptr || thrift_attr_list.empty())
      { SAI_THRIFT_LOG_ERR("Invalid input arguments."); return; }

      std::vector<sai_thrift_attribute_t>::const_iterator cit = thrift_attr_list.begin();

      for (sai_size_t i = 0; i < thrift_attr_list.size(); i++, cit++)
      {
          sai_thrift_attribute_t attribute = *cit;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
              case SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
              case SAI_HOSTIF_TRAP_ATTR_PACKET_ACTION:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
              case SAI_HOSTIF_TRAP_ATTR_TRAP_PRIORITY:
                  attr_list[i].value.u32 = attribute.value.u32;
                  break;
              case SAI_HOSTIF_TRAP_ATTR_EXCLUDE_PORT_LIST:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;
              case SAI_HOSTIF_TRAP_ATTR_TRAP_GROUP:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;
              default:
                  SAI_THRIFT_LOG_ERR("Failed to parse attribute.");
                  break;
          }
      }
  }

  void sai_thrift_parse_hostif_trap_attribute(const sai_thrift_attribute_t &thrift_attr, sai_attribute_t *attr) {
      attr->id = thrift_attr.id;
      switch (thrift_attr.id) {
          case SAI_HOSTIF_TRAP_ATTR_PACKET_ACTION:
              attr->value.s32 = thrift_attr.value.s32;
              break;
          case SAI_HOSTIF_TRAP_ATTR_TRAP_PRIORITY:
              attr->value.u32 = thrift_attr.value.u32;
              break;
          case SAI_HOSTIF_TRAP_ATTR_TRAP_GROUP:
              attr->value.oid = thrift_attr.value.oid;
              break;
          default:
              break;
      }
  }

  void sai_thrift_parser_mpls_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
              case SAI_INSEG_ENTRY_ATTR_NUM_OF_POP:
                  attr_list[i].value.u8 = attribute.value.u8;
                  break;
              case SAI_INSEG_ENTRY_ATTR_PACKET_ACTION:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
              case SAI_INSEG_ENTRY_ATTR_TRAP_PRIORITY:
                  attr_list[i].value.u8 = attribute.value.u8;
                  break;
	          case SAI_INSEG_ENTRY_ATTR_NEXT_HOP_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;
              default:
                  break;
          }
      }
  }

  sai_thrift_status_t sai_thrift_set_port_attribute(const sai_thrift_object_id_t port_id, const sai_thrift_attribute_t &thrift_attr) {
      printf("sai_thrift_set_port\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_port_api_t *port_api;
      status = sai_api_query(SAI_API_PORT, (void **) &port_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_object_id_t *buffer_profile_list = NULL;
      std::vector<sai_thrift_attribute_t> thrift_attr_list;
      thrift_attr_list.push_back(thrift_attr);
      sai_attribute_t attr;
      sai_thrift_parse_port_attributes(thrift_attr_list, &attr, &buffer_profile_list);
      status = port_api->set_port_attribute((sai_object_id_t)port_id, &attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("Failed to set port attributes, status:%d", status);
      }
      if (buffer_profile_list) free(buffer_profile_list);
      return status;
  }

  sai_thrift_status_t sai_thrift_create_fdb_entry(const sai_thrift_fdb_entry_t& thrift_fdb_entry, const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      printf("sai_thrift_create_fdb_entry\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_fdb_api_t *fdb_api;
      sai_fdb_entry_t fdb_entry;
      status = sai_api_query(SAI_API_FDB, (void **) &fdb_api);
      if (status != SAI_STATUS_SUCCESS) {
         return status;
      }
      sai_thrift_parse_fdb_entry(thrift_fdb_entry, &fdb_entry);
      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parse_fdb_attributes(thrift_attr_list, attr_list);
      uint32_t attr_count = thrift_attr_list.size();
      status = fdb_api->create_fdb_entry(&fdb_entry, attr_count, attr_list);
      free(attr_list);
      return status;
  }

  sai_thrift_status_t sai_thrift_delete_fdb_entry(const sai_thrift_fdb_entry_t& thrift_fdb_entry) {
      printf("sai_thrift_delete_fdb_entry\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_fdb_api_t *fdb_api;
      sai_fdb_entry_t fdb_entry;
      status = sai_api_query(SAI_API_FDB, (void **) &fdb_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_thrift_parse_fdb_entry(thrift_fdb_entry, &fdb_entry);
      status = fdb_api->remove_fdb_entry(&fdb_entry);
      return status;
  }

  sai_thrift_status_t sai_thrift_flush_fdb_entries(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      printf("sai_thrift_flush_fdb_entries\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_fdb_api_t *fdb_api;
      status = sai_api_query(SAI_API_FDB, (void **) &fdb_api);
      if (status != SAI_STATUS_SUCCESS) {
         return status;
      }
      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parse_fdb_flush_attributes(thrift_attr_list, attr_list);
      uint32_t attr_count = thrift_attr_list.size();
      status = fdb_api->flush_fdb_entries(gSwitchId, attr_count, attr_list);
      free(attr_list);
      return status;
  }

  sai_thrift_status_t sai_thrift_set_fdb_entry_attribute(const sai_thrift_fdb_entry_t& thrift_fdb_entry, const sai_thrift_attribute_t& thrift_attr) {
      sai_status_t status;
      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };
      sai_fdb_api_t *fdb_api;
      sai_fdb_entry_t fdb_entry;
      sai_attribute_t *attr_list = nullptr;

      printf("sai_thrift_set_fdb_entry_attribute\n");
     status = sai_api_query(SAI_API_FDB, (void **) &fdb_api);
     if (status != SAI_STATUS_SUCCESS) {
	return status;
     }

     sai_thrift_alloc_attr(attr_list, 1);
     sai_thrift_parse_fdb_attributes(thrift_attr_list, attr_list);
     sai_thrift_parse_fdb_entry(thrift_fdb_entry, &fdb_entry);

     status = fdb_api->set_fdb_entry_attribute(&fdb_entry, attr_list);
     sai_thrift_free_attr(attr_list);
     if (status != SAI_STATUS_SUCCESS)
     {
          SAI_THRIFT_LOG_ERR("Failed to set FDB attribute");
      }

      return status;
  }

void sai_thrift_get_fdb_entry_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_fdb_entry_t& thrift_fdb_entry)
{
    printf("sai_thrift_get_fdb_entry_attribute\n");
    sai_status_t status = SAI_STATUS_SUCCESS;
    sai_fdb_api_t *fdb_api;
    sai_fdb_entry_t fdb_entry;
    sai_attribute_t sai_attrs[3];
    sai_thrift_attribute_t thrift_attr;

    status = sai_api_query(SAI_API_FDB, (void **) &fdb_api);
    if (status != SAI_STATUS_SUCCESS)
    {
        SAI_THRIFT_LOG_ERR("failed to obtain fdb_api, status:%d", status);
        return;
    }

    SAI_THRIFT_FUNC_LOG();

    sai_attrs[0].id = SAI_FDB_ENTRY_ATTR_TYPE;
    sai_attrs[1].id = SAI_FDB_ENTRY_ATTR_PACKET_ACTION;
    sai_attrs[2].id = SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID;

    sai_thrift_parse_fdb_entry(thrift_fdb_entry, &fdb_entry);
    status = fdb_api->get_fdb_entry_attribute(&fdb_entry, 3, sai_attrs);
    if (status != SAI_STATUS_SUCCESS)
    {
        SAI_THRIFT_LOG_ERR("failed to obtain fdb attributes, status:%d", status);
        return;
    }

    //sai_attributes_to_sai_thrift_list(sai_attrs, 3, thrift_attr_list.attr_list);


    thrift_attr.id        = sai_attrs[0].id;
    thrift_attr.value.s32 = sai_attrs[0].value.s32;
    thrift_attr_list.attr_list.push_back(thrift_attr);

    thrift_attr.id        = sai_attrs[1].id;
    thrift_attr.value.s32 = sai_attrs[1].value.s32;
    thrift_attr_list.attr_list.push_back(thrift_attr);

    thrift_attr.id        = sai_attrs[2].id;
    thrift_attr.value.oid = sai_attrs[2].value.oid;
    thrift_attr_list.attr_list.push_back(thrift_attr);

}

void sai_thrift_parse_vlan_attributes(const std_sai_thrift_attr_vctr_t &thrift_attr_list, sai_attribute_t *attr_list)
{
    SAI_THRIFT_LOG_DBG("Called.");

    std_sai_thrift_attr_vctr_t::const_iterator cit = thrift_attr_list.begin();

    for (sai_uint32_t i = 0; i < thrift_attr_list.size(); i++, cit++)
    {
        sai_thrift_attribute_t attribute = *cit;
        attr_list[i].id = attribute.id;

        switch (attribute.id)
        {
            case SAI_VLAN_ATTR_VLAN_ID:
                attr_list[i].value.u16 = attribute.value.u16;
                break;

            case SAI_VLAN_ATTR_MAX_LEARNED_ADDRESSES:
                attr_list[i].value.u32 = attribute.value.u32;
                break;

            case SAI_VLAN_ATTR_STP_INSTANCE:
                attr_list[i].value.oid = attribute.value.oid;
                break;

            case SAI_VLAN_ATTR_LEARN_DISABLE:
                attr_list[i].value.booldata = attribute.value.booldata;
                break;
            case SAI_VLAN_ATTR_UNKNOWN_UNICAST_FLOOD_CONTROL_TYPE:
                attr_list[i].value.s32 = attribute.value.s32;
                break;
            case SAI_VLAN_ATTR_CUSTOM_IGMP_SNOOPING_ENABLE:
                attr_list[i].value.booldata = attribute.value.booldata;
                break;

            case SAI_VLAN_ATTR_IPV4_MCAST_LOOKUP_KEY_TYPE:
            case SAI_VLAN_ATTR_IPV6_MCAST_LOOKUP_KEY_TYPE:
                attr_list[i].value.booldata = attribute.value.booldata;
                break;

            case SAI_VLAN_ATTR_META_DATA:
                attr_list[i].value.u32 = attribute.value.u32;
                break;

            case SAI_VLAN_ATTR_INGRESS_ACL:
                attr_list[i].value.oid = attribute.value.oid;
                break;

            default:
                SAI_THRIFT_LOG_ERR("Failed to parse VLAN attributes.");
                break;
        }
    }
}

  void sai_thrift_parse_bridge_port_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;

          switch (attribute.id) {
              case SAI_BRIDGE_PORT_ATTR_TYPE:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;

              case SAI_BRIDGE_PORT_ATTR_ADMIN_STATE:
                  attr_list[i].value.booldata = attribute.value.booldata;
                  break;

              case SAI_BRIDGE_PORT_ATTR_VLAN_ID:
                  attr_list[i].value.u16 = attribute.value.u16;
                  break;

              case SAI_BRIDGE_PORT_ATTR_PORT_ID:
              case SAI_BRIDGE_PORT_ATTR_RIF_ID:
              case SAI_BRIDGE_PORT_ATTR_TUNNEL_ID:
              case SAI_BRIDGE_PORT_ATTR_BRIDGE_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;

              default:
                  SAI_THRIFT_LOG_ERR("Failed to parse Bridge Port attributes");
                  break;
          }
      }
  }

  void sai_thrift_parse_bridge_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;

          switch (attribute.id) {
              case SAI_BRIDGE_ATTR_TYPE:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;

              case SAI_BRIDGE_ATTR_MAX_LEARNED_ADDRESSES:
                  attr_list[i].value.u32 = attribute.value.u32;
                  break;

              case SAI_BRIDGE_ATTR_LEARN_DISABLE:
                  attr_list[i].value.booldata = attribute.value.booldata;
                  break;

			  case SAI_BRIDGE_ATTR_UNKNOWN_UNICAST_FLOOD_CONTROL_TYPE:
			  case SAI_BRIDGE_ATTR_UNKNOWN_MULTICAST_FLOOD_CONTROL_TYPE:
			  case SAI_BRIDGE_ATTR_BROADCAST_FLOOD_CONTROL_TYPE:
			  	  attr_list[i].value.s32 = attribute.value.s32;
				  break;

              default:
                  SAI_THRIFT_LOG_ERR("Failed to parse Bridge attributes.");
                  break;
          }
      }
  }

  void sai_thrift_parse_samplepacket_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) const noexcept
  {
      if (attr_list == nullptr || thrift_attr_list.empty())
      { SAI_THRIFT_LOG_ERR("Invalid input arguments."); return; }

      std::vector<sai_thrift_attribute_t>::const_iterator cit = thrift_attr_list.begin();

      for (sai_size_t i = 0; i < thrift_attr_list.size(); i++, cit++)
      {
          sai_thrift_attribute_t attribute = *cit;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
              case SAI_SAMPLEPACKET_ATTR_SAMPLE_RATE:
                  attr_list[i].value.u32 = attribute.value.u32;
                  break;
              case SAI_SAMPLEPACKET_ATTR_TYPE:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
              case SAI_SAMPLEPACKET_ATTR_MODE:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
              default:
                  SAI_THRIFT_LOG_ERR("Failed to parse attribute.");
                  break;
          }
      }
  }

  void sai_thrift_parse_tunnel_map_entry_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) const noexcept
  {
      if (attr_list == nullptr || thrift_attr_list.empty())
      { SAI_THRIFT_LOG_ERR("Invalid input arguments."); return; }

      std::vector<sai_thrift_attribute_t>::const_iterator cit = thrift_attr_list.begin();

      for (sai_size_t i = 0; i < thrift_attr_list.size(); i++, cit++)
      {
          sai_thrift_attribute_t attribute = *cit;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
		  	  case SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE:
			  	  attr_list[i].value.s32 = attribute.value.s32;
				  break;
		      case SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP:
			  case SAI_TUNNEL_MAP_ENTRY_ATTR_BRIDGE_ID_KEY:
			  case SAI_TUNNEL_MAP_ENTRY_ATTR_BRIDGE_ID_VALUE:
			  case SAI_TUNNEL_MAP_ENTRY_ATTR_VIRTUAL_ROUTER_ID_KEY:
			  case SAI_TUNNEL_MAP_ENTRY_ATTR_VIRTUAL_ROUTER_ID_VALUE:
			  	  attr_list[i].value.oid = attribute.value.oid;
			  	  break;
              case SAI_TUNNEL_MAP_ENTRY_ATTR_OECN_KEY:
			  case SAI_TUNNEL_MAP_ENTRY_ATTR_OECN_VALUE:
			  case SAI_TUNNEL_MAP_ENTRY_ATTR_UECN_KEY:
			  case SAI_TUNNEL_MAP_ENTRY_ATTR_UECN_VALUE:
                  attr_list[i].value.u8 = attribute.value.u8;
                  break;
              case SAI_TUNNEL_MAP_ENTRY_ATTR_VLAN_ID_KEY:
			  case SAI_TUNNEL_MAP_ENTRY_ATTR_VLAN_ID_VALUE:
                  attr_list[i].value.u16 = attribute.value.u16;
                  break;
              case SAI_TUNNEL_MAP_ENTRY_ATTR_VNI_ID_KEY:
			  case SAI_TUNNEL_MAP_ENTRY_ATTR_VNI_ID_VALUE:
                  attr_list[i].value.u32 = attribute.value.u32;
                  break;
              default:
                  SAI_THRIFT_LOG_ERR("Failed to parse attribute.");
                  break;
          }
      }
  }

  void sai_thrift_parse_tunnel_map_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) const noexcept
  {
      if (attr_list == nullptr || thrift_attr_list.empty())
      { SAI_THRIFT_LOG_ERR("Invalid input arguments."); return; }

      std::vector<sai_thrift_attribute_t>::const_iterator cit = thrift_attr_list.begin();

      for (sai_size_t i = 0; i < thrift_attr_list.size(); i++, cit++)
      {
          sai_thrift_attribute_t attribute = *cit;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
		  	  case SAI_TUNNEL_MAP_ATTR_TYPE:
			  	  attr_list[i].value.s32 = attribute.value.s32;
				  break;
              default:
                  SAI_THRIFT_LOG_ERR("Failed to parse attribute.");
                  break;
          }
      }
  }

  void sai_thrift_parse_tunnel_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list, sai_object_id_t **tunnel_attr_list)
  {
  	  sai_thrift_attribute_t attribute;

      if (attr_list == nullptr || thrift_attr_list.empty())
      { SAI_THRIFT_LOG_ERR("Invalid input arguments."); return; }

	  std::vector<sai_thrift_attribute_t>::const_iterator cit = thrift_attr_list.begin();
      for (sai_size_t i = 0; i < thrift_attr_list.size(); i++, cit++)
      {
          attribute = (sai_thrift_attribute_t)*cit;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
		  	  case SAI_TUNNEL_ATTR_TYPE:
			  case SAI_TUNNEL_ATTR_ENCAP_TTL_MODE:
			  case SAI_TUNNEL_ATTR_ENCAP_DSCP_MODE:
			  case SAI_TUNNEL_ATTR_ENCAP_ECN_MODE:
			  case SAI_TUNNEL_ATTR_DECAP_ECN_MODE:
			  case SAI_TUNNEL_ATTR_DECAP_TTL_MODE:
			  case SAI_TUNNEL_ATTR_DECAP_DSCP_MODE:
			  	  attr_list[i].value.s32 = attribute.value.s32;
				  break;
		      case SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE:
			  case SAI_TUNNEL_ATTR_OVERLAY_INTERFACE:
			  	  attr_list[i].value.oid = attribute.value.oid;
			  	  break;
			  case SAI_TUNNEL_ATTR_ENCAP_SRC_IP:
			  	  sai_thrift_parse_ip_address(attribute.value.ipaddr, &attr_list[i].value.ipaddr);
			  	  break;
			  case SAI_TUNNEL_ATTR_ENCAP_TTL_VAL:
			  case SAI_TUNNEL_ATTR_ENCAP_DSCP_VAL:
			  	  attr_list[i].value.u8 = attribute.value.u8;
			  	  break;
		      case SAI_TUNNEL_ATTR_ENCAP_GRE_KEY_VALID:
			  	  attr_list[i].value.booldata = attribute.value.booldata;
			  	  break;
			  case SAI_TUNNEL_ATTR_ENCAP_GRE_KEY:
			  	  attr_list[i].value.u32 = attribute.value.u32;
			  	  break;
		      case SAI_TUNNEL_ATTR_ENCAP_MAPPERS:
			  case SAI_TUNNEL_ATTR_DECAP_MAPPERS:
			  case SAI_TUNNEL_ATTR_TERM_TABLE_ENTRY_LIST:
                  {
                  *tunnel_attr_list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * attribute.value.objlist.count);
                  std::vector<sai_thrift_object_id_t>::const_iterator it2 = attribute.value.objlist.object_id_list.begin();
                  for (uint32_t j = 0; j < attribute.value.objlist.object_id_list.size(); j++, *it2++) {
                      (*tunnel_attr_list)[j] = (sai_object_id_t) *it2;
                  }
                  attr_list[i].value.objlist.count = attribute.value.objlist.count;
                  attr_list[i].value.objlist.list = *tunnel_attr_list;
			  	  }
			  	  break;
              default:
                  SAI_THRIFT_LOG_ERR("Failed to parse attribute.");
                  break;
          }
      }
  }

  void sai_thrift_parse_tunnel_term_table_entry_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list)
  {
      if (attr_list == nullptr || thrift_attr_list.empty())
      { SAI_THRIFT_LOG_ERR("Invalid input arguments."); return; }

      std::vector<sai_thrift_attribute_t>::const_iterator cit = thrift_attr_list.begin();

      for (sai_size_t i = 0; i < thrift_attr_list.size(); i++, cit++)
      {
          sai_thrift_attribute_t attribute = *cit;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
		  	  case SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_TYPE:
			  case SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_TUNNEL_TYPE:
			  	  attr_list[i].value.s32 = attribute.value.s32;
				  break;
		      case SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_VR_ID:
		      case SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_ACTION_TUNNEL_ID:
			  	  attr_list[i].value.oid = attribute.value.oid;
			  	  break;
			  case SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_DST_IP:
			  case SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_SRC_IP:
			  	  sai_thrift_parse_ip_address(attribute.value.ipaddr, &attr_list[i].value.ipaddr);
			  	  break;
              default:
                  SAI_THRIFT_LOG_ERR("Failed to parse attribute.");
                  break;
          }
      }
  }

void sai_thrift_parse_isolation_group_attributes(const std_sai_thrift_attr_vctr_t &thrift_attr_list, sai_attribute_t *attr_list)
{
    SAI_THRIFT_LOG_DBG("Called.");

    std_sai_thrift_attr_vctr_t::const_iterator cit = thrift_attr_list.begin();

    for (sai_uint32_t i = 0; i < thrift_attr_list.size(); i++, cit++)
    {
        sai_thrift_attribute_t attribute = *cit;
        attr_list[i].id = attribute.id;

        switch (attribute.id)
        {
            case SAI_ISOLATION_GROUP_ATTR_TYPE:
                attr_list[i].value.u32 = attribute.value.u32;
                break;

            default:
                  SAI_THRIFT_LOG_ERR("Failed to parse isolation group attributes");
                  break;
          }
      }
  }
void sai_thrift_parse_isolation_group_member_attributes(const std_sai_thrift_attr_vctr_t &thrift_attr_list, sai_attribute_t *attr_list)
{
    SAI_THRIFT_LOG_DBG("Called.");

    std_sai_thrift_attr_vctr_t::const_iterator cit = thrift_attr_list.begin();

    for (sai_uint32_t i = 0; i < thrift_attr_list.size(); i++, cit++)
    {
        sai_thrift_attribute_t attribute = *cit;
        attr_list[i].id = attribute.id;

        switch (attribute.id)
        {
            case SAI_ISOLATION_GROUP_MEMBER_ATTR_ISOLATION_GROUP_ID:
                attr_list[i].value.oid= attribute.value.oid;
                break;
			case SAI_ISOLATION_GROUP_MEMBER_ATTR_ISOLATION_OBJECT:
				attr_list[i].value.oid= attribute.value.oid;
                break;

            default:
                  SAI_THRIFT_LOG_ERR("Failed to parse isolation group attributes");
                  break;
          }
      }
  }

  sai_thrift_object_id_t sai_thrift_create_vlan(const std_sai_thrift_attr_vctr_t &thrift_attr_list) {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_vlan_api_t *vlan_api = nullptr;
      auto status = sai_api_query(SAI_API_VLAN, reinterpret_cast<void**>(&vlan_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get VLAN API."); return SAI_NULL_OBJECT_ID; }

      sai_attribute_t *attr_list = nullptr;
      sai_uint32_t attr_size = thrift_attr_list.size();
      sai_thrift_alloc_attr(attr_list, attr_size);
      sai_thrift_parse_vlan_attributes(thrift_attr_list, attr_list);

      sai_object_id_t vlanObjId = 0;
      status = vlan_api->create_vlan(&vlanObjId, gSwitchId, attr_size, attr_list);
      sai_thrift_free_attr(attr_list);

      if (status == SAI_STATUS_SUCCESS) { return vlanObjId; }

      SAI_THRIFT_LOG_ERR("Failed to create VLAN.");

      return SAI_NULL_OBJECT_ID;
  }

  sai_thrift_status_t sai_thrift_remove_vlan(const sai_thrift_object_id_t vlan_oid) {
      printf("sai_thrift_delete_vlan\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_vlan_api_t *vlan_api;
      status = sai_api_query(SAI_API_VLAN, (void **) &vlan_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      status = vlan_api->remove_vlan(vlan_oid);
      return status;
  }

    void sai_thrift_get_vlan_stats(std::vector<int64_t> &thrift_counters,
                                   const sai_thrift_vlan_id_t vlan_id,
                                   const std::vector<sai_thrift_vlan_stat_counter_t> &thrift_counter_ids,
                                   const int32_t number_of_counters)
    {
        printf("sai_thrift_get_vlan_stats\n");
        sai_status_t status = SAI_STATUS_SUCCESS;
        sai_vlan_api_t *vlan_api;
        status = sai_api_query(SAI_API_VLAN, (void **) &vlan_api);

        if (status != SAI_STATUS_SUCCESS) { return; }

        sai_stat_id_t *counter_ids = (sai_stat_id_t *) malloc(sizeof(sai_vlan_stat_t) * thrift_counter_ids.size());
        std::vector<int32_t>::const_iterator it = thrift_counter_ids.begin();
        uint64_t *counters = (uint64_t *) malloc(sizeof(uint64_t) * thrift_counter_ids.size());

        for(uint32_t i = 0; i < thrift_counter_ids.size(); i++, it++)
        { counter_ids[i] = (sai_vlan_stat_t) *it; }

        status = vlan_api->get_vlan_stats((sai_vlan_id_t) vlan_id,
                                          number_of_counters,
                                          counter_ids,
                                          counters);

        for (uint32_t i = 0; i < thrift_counter_ids.size(); i++) { thrift_counters.push_back(counters[i]); }

        free(counter_ids);
        free(counters);

        return;
    }


   sai_thrift_status_t sai_thrift_set_vlan_attribute(const sai_thrift_object_id_t vlan_id, const sai_thrift_attribute_t &thrift_attr) {
      printf("sai_thrift_set_vlan\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_vlan_api_t *vlan_api;
      status = sai_api_query(SAI_API_VLAN, (void **) &vlan_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }

      std::vector<sai_thrift_attribute_t> thrift_attr_list;
      thrift_attr_list.push_back(thrift_attr);

      sai_attribute_t *attr_list = nullptr;
      sai_uint32_t attr_size = 1;
      sai_thrift_alloc_attr(attr_list, attr_size);
      sai_thrift_parse_vlan_attributes(thrift_attr_list, attr_list);
      status = vlan_api->set_vlan_attribute((sai_object_id_t)vlan_id, attr_list);
      sai_thrift_free_attr(attr_list);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("Failed to set vlan attributes.");
      }
      return status;
  }


void sai_thrift_get_vlan_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t vlan_id)
{
    printf("sai_thrift_get_vlan_attribute\n");
    sai_status_t status = SAI_STATUS_SUCCESS;
    sai_vlan_api_t *vlan_api;
    sai_attribute_t sai_attrs[10];
    sai_thrift_attribute_t thrift_vlan_member_list_attribute;
    sai_thrift_attribute_t thrift_attr;
    sai_object_list_t *vlan_member_list_object;
    int i = 0;
    status = sai_api_query(SAI_API_VLAN, (void **) &vlan_api);
    if (status != SAI_STATUS_SUCCESS)
    {
        return;
    }

    sai_attrs[i].id = SAI_VLAN_ATTR_VLAN_ID;
    i++;

    sai_attrs[i].id = SAI_VLAN_ATTR_MEMBER_LIST;
    sai_attrs[i].value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * 128);
    sai_attrs[i].value.objlist.count = 128;
    i++;
    sai_attrs[i].id = SAI_VLAN_ATTR_MAX_LEARNED_ADDRESSES;
    i++;
    //sai_attrs[3].id = SAI_VLAN_ATTR_STP_INSTANCE;
    //i++;
    sai_attrs[i].id = SAI_VLAN_ATTR_LEARN_DISABLE;
    i++;
    sai_attrs[i].id = SAI_VLAN_ATTR_UNKNOWN_UNICAST_FLOOD_CONTROL_TYPE;
    i++;
    //sai_attrs[i].id = SAI_VLAN_ATTR_CUSTOM_IGMP_SNOOPING_ENABLE;
    //i++;
    vlan_api->get_vlan_attribute(vlan_id, i, sai_attrs);

    thrift_attr_list.attr_count = 1;
    std::vector < sai_thrift_attribute_t > & attr_list = thrift_attr_list.attr_list;
    thrift_vlan_member_list_attribute.id = SAI_VLAN_ATTR_MEMBER_LIST;
    thrift_vlan_member_list_attribute.value.objlist.count = sai_attrs[1].value.objlist.count;
    std::vector < sai_thrift_object_id_t > & vlan_member_list = thrift_vlan_member_list_attribute.value.objlist.object_id_list;
    vlan_member_list_object = &sai_attrs[1].value.objlist;
    for (int index = 0; index < sai_attrs[1].value.objlist.count; index++)
    {
        vlan_member_list.push_back((sai_thrift_object_id_t) vlan_member_list_object->list[index]);
    }
    attr_list.push_back(thrift_vlan_member_list_attribute);

    thrift_attr.id        = sai_attrs[0].id;
    thrift_attr.value.u16 = sai_attrs[0].value.u16;
    thrift_attr_list.attr_list.push_back(thrift_attr);

    thrift_attr.id        = sai_attrs[2].id;
    thrift_attr.value.u32 = sai_attrs[2].value.u32;
    thrift_attr_list.attr_list.push_back(thrift_attr);

    thrift_attr.id        = sai_attrs[3].id;
    thrift_attr.value.oid = sai_attrs[3].value.oid;
    thrift_attr_list.attr_list.push_back(thrift_attr);

    thrift_attr.id        = sai_attrs[4].id;
    thrift_attr.value.booldata = sai_attrs[4].value.booldata;
    thrift_attr_list.attr_list.push_back(thrift_attr);

    thrift_attr.id        = sai_attrs[5].id;
    thrift_attr.value.s32 = sai_attrs[5].value.s32;
    thrift_attr_list.attr_list.push_back(thrift_attr);

    thrift_attr.id        = sai_attrs[6].id;
    thrift_attr.value.booldata = sai_attrs[6].value.booldata;
    thrift_attr_list.attr_list.push_back(thrift_attr);

    free(sai_attrs[1].value.objlist.list);
}

  sai_thrift_object_id_t sai_thrift_create_vlan_member(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      printf("sai_thrift_create_vlan_member\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_vlan_api_t *vlan_api;
      sai_object_id_t vlan_member_id = 0;
      status = sai_api_query(SAI_API_VLAN, (void **) &vlan_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parse_vlan_member_attributes(thrift_attr_list, attr_list);
      uint32_t attr_count = thrift_attr_list.size();
      vlan_api->create_vlan_member(&vlan_member_id, gSwitchId, attr_count, attr_list);
      return vlan_member_id;
  }

  void sai_thrift_parse_vlan_member_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
              case SAI_VLAN_MEMBER_ATTR_VLAN_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;
              case SAI_VLAN_MEMBER_ATTR_BRIDGE_PORT_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;
              case SAI_VLAN_MEMBER_ATTR_VLAN_TAGGING_MODE:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
          }
      }
  }



  void sai_thrift_get_vlan_member_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t vlan_member_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_vlan_api_t *vlan_api;
      sai_attribute_t attr[3];

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_VLAN, (void **) &vlan_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain vlan_api, status:%d", status);
          return;
      }

      attr[0].id = SAI_VLAN_MEMBER_ATTR_VLAN_ID;
      attr[1].id = SAI_VLAN_MEMBER_ATTR_BRIDGE_PORT_ID;
      attr[2].id = SAI_VLAN_MEMBER_ATTR_VLAN_TAGGING_MODE;

      status = vlan_api->get_vlan_member_attribute(vlan_member_id, 3, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain vlan member attributes, status:%d", status);
          return;
      }

      sai_attributes_to_sai_thrift_list(attr, 3, thrift_attr_list.attr_list);
  }

  sai_thrift_status_t sai_thrift_remove_vlan_member(const sai_thrift_object_id_t vlan_member_id) {
      printf("sai_thrift_remove_vlan_member\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_vlan_api_t *vlan_api;
      status = sai_api_query(SAI_API_VLAN, (void **) &vlan_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      status = vlan_api->remove_vlan_member((sai_object_id_t) vlan_member_id);
      return status;
  }

  void sai_thrift_get_vlan_id(sai_thrift_result_t &ret, sai_thrift_object_id_t vlan_id)
  {
      sai_attribute_t vlan_attr;
      sai_vlan_api_t *vlan_api;

      SAI_THRIFT_FUNC_LOG();

      ret.status = sai_api_query(SAI_API_VLAN, (void **) &vlan_api);
      if (ret.status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain vlan_api, status:%d", ret.status);
          return;
      }

      vlan_attr.id = SAI_VLAN_ATTR_VLAN_ID;
      ret.status = vlan_api->get_vlan_attribute((sai_object_id_t)vlan_id, 1, &vlan_attr);
      if (ret.status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to get vlan ID, status:%d", ret.status);
          return;
      }

      ret.data.u16 = vlan_attr.value.u16;
  }

  sai_thrift_object_id_t sai_thrift_create_virtual_router(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      printf("sai_thrift_create_virtual_router\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_virtual_router_api_t *vr_api;
      sai_object_id_t vr_id = 0;
      status = sai_api_query(SAI_API_VIRTUAL_ROUTER, (void **) &vr_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parse_vr_attributes(thrift_attr_list, attr_list);
      uint32_t attr_count = thrift_attr_list.size();
      vr_api->create_virtual_router(&vr_id, gSwitchId, attr_count, attr_list);
      free(attr_list);
      return vr_id;
  }

  sai_thrift_status_t sai_thrift_remove_virtual_router(const sai_thrift_object_id_t vr_id) {
      printf("sai_thrift_remove_virtual_router\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_virtual_router_api_t *vr_api;
      status = sai_api_query(SAI_API_VIRTUAL_ROUTER, (void **) &vr_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      status = vr_api->remove_virtual_router((sai_object_id_t)vr_id);
      return status;
  }
  sai_thrift_status_t sai_thrift_set_virtual_router_attribute(const sai_thrift_object_id_t vr_id,
                                                           const sai_thrift_attribute_t& thrift_attr)
  {
      printf("sai_thrift_set_virtual_router_attribute\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_virtual_router_api_t *vr_api;
      sai_attribute_t attr;
      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      status = sai_api_query(SAI_API_VIRTUAL_ROUTER, (void **) &vr_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to set virtual router attributes, status:%d", status);
          return status;
      }

      sai_thrift_parse_vr_attributes(thrift_attr_list, &attr);

      return vr_api->set_virtual_router_attribute(vr_id, &attr);
  }

  void sai_thrift_get_virtual_router_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t vr_id) {
      printf("sai_thrift_get_virtual_router_attribute\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_virtual_router_api_t *vr_api;
      sai_attribute_t attr[3];
      sai_thrift_attribute_t thrift_attr;

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_VIRTUAL_ROUTER, (void **) &vr_api);
      if (status != SAI_STATUS_SUCCESS) {
          return;
      }

      attr[0].id = SAI_VIRTUAL_ROUTER_ATTR_ADMIN_V4_STATE;
      attr[1].id = SAI_VIRTUAL_ROUTER_ATTR_ADMIN_V6_STATE;
      attr[2].id = SAI_VIRTUAL_ROUTER_ATTR_SRC_MAC_ADDRESS;

      status = vr_api->get_virtual_router_attribute(vr_id, 3, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to get virtual router attributes, status:%d", status);
          thrift_attr_list.status = status;
          return;
      }
      sai_attributes_booldata_to_sai_thrift_list(attr, 2, thrift_attr_list.attr_list);

      thrift_attr.id        = attr[2].id;
      thrift_attr.value.mac = sai_thrift_mac_to_string(attr[2].value.mac);
      thrift_attr_list.attr_list.push_back(thrift_attr);

  }

  sai_thrift_status_t sai_thrift_create_route(const sai_thrift_route_entry_t &thrift_route_entry, const std::vector<sai_thrift_attribute_t> & thrift_attr_list)
  {
      printf("sai_thrift_create_route\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_route_api_t *route_api;
      sai_route_entry_t route_entry;
      status = sai_api_query(SAI_API_ROUTE, (void **) &route_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_thrift_parse_route_entry(thrift_route_entry, &route_entry);
      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parse_route_attributes(thrift_attr_list, attr_list);
      uint32_t attr_count = thrift_attr_list.size();
      status = route_api->create_route_entry(&route_entry, attr_count, attr_list);
      free(attr_list);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to set create attributes, status:%d", status);
      }
      return status;
  }

  sai_thrift_status_t sai_thrift_remove_route(const sai_thrift_route_entry_t &thrift_route_entry) {
      printf("sai_thrift_remove_route\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_route_api_t *route_api;
      sai_route_entry_t route_entry;
      status = sai_api_query(SAI_API_ROUTE, (void **) &route_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_thrift_parse_route_entry(thrift_route_entry, &route_entry);
      status = route_api->remove_route_entry(&route_entry);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to set remove attributes, status:%d", status);
      }
      return status;
  }

  sai_thrift_status_t sai_thrift_set_route_attribute(const sai_thrift_route_entry_t& thrift_route_entry, const sai_thrift_attribute_t& thrift_attr) {
      printf("sai_thrift_set_route_attribute\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };
      sai_route_api_t *route_api;
      sai_route_entry_t route_entry;
      sai_attribute_t *attr_list = nullptr;
      status = sai_api_query(SAI_API_ROUTE, (void **) &route_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_thrift_alloc_attr(attr_list, 1);
      sai_thrift_parse_route_entry(thrift_route_entry, &route_entry);
      sai_thrift_parse_route_attributes(thrift_attr_list, attr_list);
      status = route_api->set_route_entry_attribute(&route_entry, attr_list);
      sai_thrift_free_attr(attr_list);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to set route attributes, status:%d", status);
      }
      return status;
  }

  void sai_thrift_get_route_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_route_entry_t& thrift_route_entry)
  {
      printf("sai_thrift_get_route_attribute\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_route_api_t *route_api;
      sai_route_entry_t route_entry;
      sai_attribute_t attr[SAI_ROUTE_ENTRY_ATTR_END];
      sai_thrift_attribute_t thrift_attr;
      uint32_t attr_cnt = 0;

      status = sai_api_query(SAI_API_ROUTE, (void **) &route_api);
      if (status != SAI_STATUS_SUCCESS)
      {
          thrift_attr_list.status = status;
          return;
      }

      sai_thrift_parse_route_entry(thrift_route_entry, &route_entry);

      attr[attr_cnt++].id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION;
      attr[attr_cnt++].id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID;
      attr[attr_cnt++].id = SAI_ROUTE_ENTRY_ATTR_META_DATA;

      status = route_api->get_route_entry_attribute(&route_entry, attr_cnt, attr);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to get route attributes, status:%d", status);
          thrift_attr_list.status = status;
          return;
      }

      thrift_attr.id        = attr[0].id;
      thrift_attr.value.s32 = attr[0].value.s32;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = attr[1].id;
      thrift_attr.value.oid = attr[1].value.oid;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = attr[2].id;
      thrift_attr.value.u32 = attr[2].value.u32;
      thrift_attr_list.attr_list.push_back(thrift_attr);

  }


  sai_thrift_object_id_t sai_thrift_create_router_interface(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      printf("sai_thrift_create_router_interface\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_router_interface_api_t *rif_api;
      sai_object_id_t rif_id = 0;
      status = sai_api_query(SAI_API_ROUTER_INTERFACE, (void **) &rif_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parse_router_interface_attributes(thrift_attr_list, attr_list);
      uint32_t attr_count = thrift_attr_list.size();
      status = rif_api->create_router_interface(&rif_id, gSwitchId, attr_count, attr_list);
      free(attr_list);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to create router interface, status:%d", status);
      }
      return rif_id;
  }

  sai_thrift_status_t sai_thrift_remove_router_interface(const sai_thrift_object_id_t rif_id) {
      printf("sai_thrift_remove_router_interface\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_router_interface_api_t *rif_api;
      status = sai_api_query(SAI_API_ROUTER_INTERFACE, (void **) &rif_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      status = rif_api->remove_router_interface((sai_object_id_t)rif_id);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to remove router interface, status:%d", status);
      }
      return status;
  }

  sai_thrift_status_t sai_thrift_set_router_interface_attribute(const sai_thrift_object_id_t rif_id, const sai_thrift_attribute_t &thrift_attr) {
      printf("sai_thrift_set_router_interface\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_router_interface_api_t *rif_api;
      status = sai_api_query(SAI_API_ROUTER_INTERFACE, (void **) &rif_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      std::vector<sai_thrift_attribute_t> thrift_attr_list;
      thrift_attr_list.push_back(thrift_attr);
      sai_attribute_t attr;
      sai_thrift_parse_router_interface_attributes(thrift_attr_list, &attr);
      status = rif_api->set_router_interface_attribute((sai_object_id_t)rif_id, &attr);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to set router interface attributes, status:%d", status);
      }
      return status;
  }

  void sai_thrift_get_router_interface_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t rif_id) {
      printf("sai_thrift_get_router_interface_attribute\n");

      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_router_interface_api_t *rif_api;
      sai_attribute_t attr[SAI_VIRTUAL_ROUTER_ATTR_END];
      sai_thrift_attribute_t thrift_attr;
      uint32_t attr_cnt = 0;

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_ROUTER_INTERFACE, (void **) &rif_api);
      if (status != SAI_STATUS_SUCCESS) {
          return;
      }

      attr_cnt = 0;
      attr[attr_cnt++].id = SAI_ROUTER_INTERFACE_ATTR_ADMIN_V4_STATE;
      attr[attr_cnt++].id = SAI_ROUTER_INTERFACE_ATTR_ADMIN_V6_STATE;
      attr[attr_cnt++].id = SAI_ROUTER_INTERFACE_ATTR_V4_MCAST_ENABLE;
      attr[attr_cnt++].id = SAI_ROUTER_INTERFACE_ATTR_V6_MCAST_ENABLE;
      status = rif_api->get_router_interface_attribute(rif_id, attr_cnt, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("Failed to get router interface attributes, status:%d", status);
          thrift_attr_list.status = status;
          return;
      }
      sai_attributes_booldata_to_sai_thrift_list(attr, attr_cnt, thrift_attr_list.attr_list);

      attr_cnt = 0;
      attr[attr_cnt++].id = SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID;
      attr[attr_cnt++].id = SAI_ROUTER_INTERFACE_ATTR_PORT_ID;
      attr[attr_cnt++].id = SAI_ROUTER_INTERFACE_ATTR_VLAN_ID;

      status = rif_api->get_router_interface_attribute(rif_id, attr_cnt, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("Failed to get router interface attributes, status:%d", status);
          thrift_attr_list.status = status;
          return;
      }
      sai_attributes_to_sai_thrift_list(attr, attr_cnt, thrift_attr_list.attr_list);

      attr_cnt = 0;
      attr[attr_cnt++].id = SAI_ROUTER_INTERFACE_ATTR_TYPE;
      attr[attr_cnt++].id = SAI_ROUTER_INTERFACE_ATTR_NEIGHBOR_MISS_PACKET_ACTION;
      status = rif_api->get_router_interface_attribute(rif_id, attr_cnt, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("Failed to get router interface attributes, status:%d", status);
          thrift_attr_list.status = status;
          return;
      }
      sai_attributes_s32_to_sai_thrift_list(attr, attr_cnt, thrift_attr_list.attr_list);

      attr_cnt = 0;
      attr[attr_cnt++].id = SAI_ROUTER_INTERFACE_ATTR_MTU;
      status = rif_api->get_router_interface_attribute(rif_id, attr_cnt, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("Failed to get router interface attributes, status:%d", status);
          thrift_attr_list.status = status;
          return;
      }
      sai_attributes_u32_to_sai_thrift_list(attr, attr_cnt, thrift_attr_list.attr_list);

      attr_cnt = 0;
      attr[attr_cnt++].id = SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS;
      status = rif_api->get_router_interface_attribute(rif_id, attr_cnt, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("Failed to get router interface attributes, status:%d", status);
          thrift_attr_list.status = status;
          return;
      }
      thrift_attr.id        = attr[0].id;
      thrift_attr.value.mac = sai_thrift_mac_to_string(attr[0].value.mac);
      thrift_attr_list.attr_list.push_back(thrift_attr);


  }

  void sai_thrift_router_interface_get_stats(std::vector<int64_t> &thrift_counters,
  	const sai_thrift_object_id_t rif_id,
  	const std::vector<sai_thrift_router_interface_stat_counter_t> &thrift_counter_ids,
  	int32_t number_of_counters)
  	{
		printf("sai_thrift_get_router_interface_stats\n");
        sai_status_t status = SAI_STATUS_SUCCESS;
        sai_router_interface_api_t *rif_api;
        status = sai_api_query(SAI_API_ROUTER_INTERFACE, (void **) &rif_api);

        if (status != SAI_STATUS_SUCCESS) { return; }

        sai_stat_id_t *counter_ids = (sai_stat_id_t *) malloc(sizeof(sai_router_interface_stat_t) * thrift_counter_ids.size());
        std::vector<int32_t>::const_iterator it = thrift_counter_ids.begin();
        uint64_t *counters = (uint64_t *) malloc(sizeof(uint64_t) * thrift_counter_ids.size());
		memset(counter_ids, 0, sizeof(sai_router_interface_stat_t) * thrift_counter_ids.size());
		memset(counters, 0, sizeof(uint64_t) * thrift_counter_ids.size());

        for(uint32_t i = 0; i < thrift_counter_ids.size(); i++, it++)
        {
        	counter_ids[i] = (sai_router_interface_stat_t) *it;
		}

        status = rif_api->get_router_interface_stats(rif_id,
                                          number_of_counters,
                                          counter_ids,
                                          counters);

        for (uint32_t i = 0; i < thrift_counter_ids.size(); i++) { thrift_counters.push_back(counters[i]); }

        free(counter_ids);
        free(counters);

        return;
  	}

  void sai_thrift_router_interface_get_stats_ext(std::vector<int64_t> &thrift_counters,
  	const sai_thrift_object_id_t rif_id,
  	const std::vector<sai_thrift_router_interface_stat_counter_t> &thrift_counter_ids,
  	int8_t mode,
  	int32_t number_of_counters)
  	{
		printf("sai_thrift_router_interface_get_stats_ext\n");
        sai_status_t status = SAI_STATUS_SUCCESS;
        sai_router_interface_api_t *rif_api;
        status = sai_api_query(SAI_API_ROUTER_INTERFACE, (void **) &rif_api);

        if (status != SAI_STATUS_SUCCESS) { return; }

        sai_stat_id_t *counter_ids = (sai_stat_id_t *) malloc(sizeof(sai_router_interface_stat_t) * thrift_counter_ids.size());
        std::vector<int32_t>::const_iterator it = thrift_counter_ids.begin();
        uint64_t *counters = (uint64_t *) malloc(sizeof(uint64_t) * thrift_counter_ids.size());
		memset(counter_ids, 0, sizeof(sai_router_interface_stat_t) * thrift_counter_ids.size());
		memset(counters, 0, sizeof(uint64_t) * thrift_counter_ids.size());

        for(uint32_t i = 0; i < thrift_counter_ids.size(); i++, it++)
        {
        	counter_ids[i] = (sai_router_interface_stat_t) *it;
		}

        status = rif_api->get_router_interface_stats_ext(rif_id,
                                          number_of_counters,
                                          counter_ids,
                                          (sai_stats_mode_t)mode,
                                          counters);

        for (uint32_t i = 0; i < thrift_counter_ids.size(); i++) { thrift_counters.push_back(counters[i]); }

        free(counter_ids);
        free(counters);

        return;
  	}

  sai_thrift_status_t sai_thrift_router_interface_clear_stats(const sai_thrift_object_id_t rif_id,
  	const std::vector<sai_thrift_router_interface_stat_counter_t> &thrift_counter_ids,
  	int32_t number_of_counters)
  	{
  		printf("sai_thrift_router_interface_clear_stats\n");
        sai_status_t status = SAI_STATUS_SUCCESS;
        sai_router_interface_api_t *rif_api;
        status = sai_api_query(SAI_API_ROUTER_INTERFACE, (void **) &rif_api);

        if (status != SAI_STATUS_SUCCESS) { return status; }

        sai_stat_id_t *counter_ids = (sai_stat_id_t *) malloc(sizeof(sai_router_interface_stat_t) * thrift_counter_ids.size());
        std::vector<int32_t>::const_iterator it = thrift_counter_ids.begin();
        uint64_t *counters = (uint64_t *) malloc(sizeof(uint64_t) * thrift_counter_ids.size());
		memset(counter_ids, 0, sizeof(sai_router_interface_stat_t) * thrift_counter_ids.size());
		memset(counters, 0, sizeof(uint64_t) * thrift_counter_ids.size());

        for(uint32_t i = 0; i < thrift_counter_ids.size(); i++, it++)
        {
        	counter_ids[i] = (sai_router_interface_stat_t) *it;
		}

        status = rif_api->clear_router_interface_stats(rif_id,
                                          number_of_counters,
                                          counter_ids);

        free(counter_ids);
        free(counters);

        return status;
  	}

  sai_thrift_object_id_t sai_thrift_create_next_hop(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      printf("sai_thrift_create_next_hop\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_next_hop_api_t *nhop_api;
      sai_object_id_t nhop_id = 0;
      status = sai_api_query(SAI_API_NEXT_HOP, (void **) &nhop_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }

	  sai_uint32_t     *buffer_profile_list1 = NULL;
      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parse_next_hop_attributes(thrift_attr_list, attr_list, &buffer_profile_list1);
      uint32_t attr_count = thrift_attr_list.size();
      status = nhop_api->create_next_hop(&nhop_id, gSwitchId, attr_count, attr_list);
      free(attr_list);
      if (buffer_profile_list1)
      {
          free(buffer_profile_list1);
      }
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to create next hop, status:%d", status);
      }
      return nhop_id;
  }

  sai_thrift_status_t sai_thrift_remove_next_hop(const sai_thrift_object_id_t next_hop_id) {
      printf("sai_thrift_remove_next_hop\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_next_hop_api_t *nhop_api;
      status = sai_api_query(SAI_API_NEXT_HOP, (void **) &nhop_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      status = nhop_api->remove_next_hop((sai_object_id_t)next_hop_id);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to remove next hop, status:%d", status);
      }
      return status;
  }


  void sai_thrift_get_next_hop_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t next_hop_id) {
      printf("sai_thrift_get_next_hop_attribute\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_next_hop_api_t *nhop_api;
      sai_attribute_t attr[3];
      sai_thrift_attribute_t thrift_attr;

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_NEXT_HOP, (void **) &nhop_api);
      if (status != SAI_STATUS_SUCCESS) {
          return;
      }

      attr[0].id = SAI_NEXT_HOP_ATTR_TYPE;
      attr[1].id = SAI_NEXT_HOP_ATTR_IP;
      attr[2].id = SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID;

      status = nhop_api->get_next_hop_attribute(next_hop_id, 3, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("Failed to get next hop attributes, status:%d", status);
          thrift_attr_list.status = status;
          return;
      }

      thrift_attr.id        = attr[0].id;
      thrift_attr.value.s32 = attr[0].value.s32;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = attr[1].id;
      thrift_attr.value.ipaddr.addr_family = attr[1].value.ipaddr.addr_family;
      if (SAI_IP_ADDR_FAMILY_IPV4 == attr[1].value.ipaddr.addr_family)
      {
          thrift_attr.value.ipaddr.addr.ip4 = sai_thrift_v4_ip_to_string(attr[1].value.ipaddr.addr.ip4);
      }
      else
      {

      }
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = attr[2].id;
      thrift_attr.value.oid = attr[2].value.oid;
      thrift_attr_list.attr_list.push_back(thrift_attr);

  }

  sai_thrift_object_id_t sai_thrift_create_lag(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      printf("sai_thrift_create_lag\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_lag_api_t *lag_api;
      sai_object_id_t lag_id = 0;

      status = sai_api_query(SAI_API_LAG, (void **) &lag_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }

      status = lag_api->create_lag(&lag_id, gSwitchId, 0, nullptr);
      return lag_id;
  }

  sai_thrift_status_t sai_thrift_remove_lag(const sai_thrift_object_id_t lag_id) {
      printf("sai_thrift_remove_lag\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_lag_api_t *lag_api;
      status = sai_api_query(SAI_API_LAG, (void **) &lag_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      status = lag_api->remove_lag((sai_object_id_t)lag_id);
      return status;
  }

  sai_thrift_status_t sai_thrift_set_lag_attribute(const sai_thrift_object_id_t lag_id, const sai_thrift_attribute_t& thrift_attr) {
      sai_status_t status;
      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };
      sai_lag_api_t *lag_api;
      sai_attribute_t *attr_list = nullptr;
      printf("sai_thrift_set_lag_attribute\n");

      status = sai_api_query(SAI_API_LAG, (void **) &lag_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }

      sai_thrift_alloc_attr(attr_list, 1);
      sai_thrift_parse_lag_attributes(thrift_attr_list, attr_list);

      status = lag_api->set_lag_attribute(lag_id, attr_list);
      sai_thrift_free_attr(attr_list);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to set LAG attribute");
          return status;
      }

      return status;
  }


void sai_thrift_get_lag_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t lag_id)
{
    printf("sai_thrift_get_lag_attribute\n");
    sai_status_t status = SAI_STATUS_SUCCESS;
    sai_lag_api_t *lag_api;
    sai_attribute_t sai_attrs[10];
    sai_thrift_attribute_t thrift_port_list_attribute;
    sai_thrift_attribute_t thrift_attr;
    sai_object_list_t *port_list_object;
    int i = 0;
    status = sai_api_query(SAI_API_LAG, (void **) &lag_api);
    if (status != SAI_STATUS_SUCCESS)
    {
        return;
    }


    sai_attrs[i].id = SAI_LAG_ATTR_PORT_LIST;
    sai_attrs[i].value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * 128);
    sai_attrs[i].value.objlist.count = 128;
    i++;

    sai_attrs[i].id = SAI_LAG_ATTR_PORT_VLAN_ID;
    i++;
    sai_attrs[i].id = SAI_LAG_ATTR_DEFAULT_VLAN_PRIORITY;
    i++;
    sai_attrs[i].id = SAI_LAG_ATTR_DROP_UNTAGGED;
    i++;
    sai_attrs[i].id = SAI_LAG_ATTR_DROP_TAGGED;
    i++;
    lag_api->get_lag_attribute(lag_id, i, sai_attrs);

    thrift_attr_list.attr_count = 1;
    std::vector < sai_thrift_attribute_t > & attr_list = thrift_attr_list.attr_list;
    thrift_port_list_attribute.id = SAI_LAG_ATTR_PORT_LIST;
    thrift_port_list_attribute.value.objlist.count = sai_attrs[0].value.objlist.count;
    std::vector < sai_thrift_object_id_t > & port_list = thrift_port_list_attribute.value.objlist.object_id_list;
    port_list_object = &sai_attrs[0].value.objlist;
    for (int index = 0; index < sai_attrs[0].value.objlist.count; index++)
    {
        port_list.push_back((sai_thrift_object_id_t) port_list_object->list[index]);
    }
    attr_list.push_back(thrift_port_list_attribute);

    thrift_attr.id        = sai_attrs[1].id;
    thrift_attr.value.u16 = sai_attrs[1].value.u16;
    thrift_attr_list.attr_list.push_back(thrift_attr);

    thrift_attr.id        = sai_attrs[2].id;
    thrift_attr.value.u8 = sai_attrs[2].value.u8;
    thrift_attr_list.attr_list.push_back(thrift_attr);

    thrift_attr.id        = sai_attrs[3].id;
    thrift_attr.value.booldata = sai_attrs[3].value.booldata;
    thrift_attr_list.attr_list.push_back(thrift_attr);

    thrift_attr.id        = sai_attrs[4].id;
    thrift_attr.value.booldata = sai_attrs[4].value.booldata;
    thrift_attr_list.attr_list.push_back(thrift_attr);


    free(sai_attrs[0].value.objlist.list);
}

  sai_thrift_object_id_t sai_thrift_create_lag_member(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      printf("sai_thrift_create_lag_member\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_lag_api_t *lag_api;
      sai_object_id_t lag_member_id;
      status = sai_api_query(SAI_API_LAG, (void **) &lag_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parse_lag_member_attributes(thrift_attr_list, attr_list);
      uint32_t attr_count = thrift_attr_list.size();
      status = lag_api->create_lag_member(&lag_member_id, gSwitchId, attr_count, attr_list);
      return lag_member_id;
  }

  sai_thrift_status_t sai_thrift_remove_lag_member(const sai_thrift_object_id_t lag_member_id) {
      printf("sai_thrift_remove_lag_member\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_lag_api_t *lag_api;
      status = sai_api_query(SAI_API_LAG, (void **) &lag_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      status = lag_api->remove_lag_member(lag_member_id);
      return status;
  }


  sai_thrift_status_t sai_thrift_set_lag_member_attribute(const sai_thrift_object_id_t lag_member_id, const sai_thrift_attribute_t& thrift_attr) {
      sai_status_t status;
      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };
      sai_lag_api_t *lag_api;
      sai_attribute_t *attr_list = nullptr;
      printf("sai_thrift_set_lag_member_attribute\n");


      status = sai_api_query(SAI_API_LAG, (void **) &lag_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }

      sai_thrift_alloc_attr(attr_list, 1);
      sai_thrift_parse_lag_member_attributes(thrift_attr_list, attr_list);

      status = lag_api->set_lag_member_attribute(lag_member_id, attr_list);
      sai_thrift_free_attr(attr_list);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to set LAG member attribute");
          return status;
      }

      return status;
  }


  void sai_thrift_get_lag_member_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t lag_member_id)
  {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_attribute_t sai_attrs[2];
      sai_lag_api_t *lag_api;

      status = sai_api_query(SAI_API_LAG, (void **) &lag_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain lag_api, status:%d", status);
          return;
      }

      SAI_THRIFT_FUNC_LOG();

      sai_attrs[0].id = SAI_LAG_MEMBER_ATTR_LAG_ID;
      sai_attrs[1].id = SAI_LAG_MEMBER_ATTR_PORT_ID;

      status = lag_api->get_lag_member_attribute(lag_member_id, 2, sai_attrs);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain lag member attributes, status:%d", status);
          return;
      }

      sai_attributes_to_sai_thrift_list(sai_attrs, 2, thrift_attr_list.attr_list);
  }

  sai_thrift_object_id_t sai_thrift_create_stp_entry(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      printf("sai_thrift_create_stp\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_stp_api_t *stp_api;
      sai_vlan_id_t *vlan_list;
      sai_object_id_t stp_id;
      status = sai_api_query(SAI_API_STP, (void **) &stp_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parse_stp_attributes(thrift_attr_list, attr_list, &vlan_list);
      uint32_t attr_count = thrift_attr_list.size();
      status = (sai_object_id_t) stp_api->create_stp(&stp_id, gSwitchId, attr_count, attr_list);
      if (vlan_list) free(vlan_list);
      free(attr_list);
      return stp_id;
  }

  sai_thrift_status_t sai_thrift_remove_stp_entry(const sai_thrift_object_id_t stp_id) {
      printf("sai_thrift_remove_stp\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_stp_api_t *stp_api;
      status = sai_api_query(SAI_API_STP, (void **) &stp_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      status = (sai_thrift_status_t) stp_api->remove_stp(stp_id);
      return status;
  }

  sai_thrift_status_t sai_thrift_set_stp_port_state(const sai_thrift_object_id_t stp_id, const sai_thrift_object_id_t port_id, const sai_thrift_port_stp_port_state_t stp_port_state) {
    printf("sai_thrift_set_stp_port_state\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_stp_api_t *stp_api;
      status = sai_api_query(SAI_API_STP, (void **) &stp_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_attribute_t attr[1];
      std::memset(attr, '\0', sizeof(attr));
      attr[0].id = SAI_STP_PORT_ATTR_STATE;
      attr[0].value.s32 = stp_port_state;
      status = stp_api->set_stp_port_attribute(port_id, attr);
      return status;
  }

  sai_thrift_port_stp_port_state_t sai_thrift_get_stp_port_state(const sai_thrift_object_id_t stp_id, const sai_thrift_object_id_t port_id) {
    printf("sai_thrift_get_stp_port_state\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_stp_api_t *stp_api;
      status = sai_api_query(SAI_API_STP, (void **) &stp_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_attribute_t attr[1];
      std::memset(attr, '\0', sizeof(attr));
      attr[0].id = SAI_STP_PORT_ATTR_STATE;
      status = stp_api->get_stp_port_attribute(port_id, 1, attr);
      return (sai_thrift_port_stp_port_state_t) attr[0].value.s32;
  }

  sai_thrift_status_t sai_thrift_create_neighbor_entry(const sai_thrift_neighbor_entry_t& thrift_neighbor_entry, const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      printf("sai_thrift_create_neighbor_entry\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_neighbor_api_t *neighbor_api;
      status = sai_api_query(SAI_API_NEIGHBOR, (void **) &neighbor_api);
      sai_neighbor_entry_t neighbor_entry;
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_thrift_parse_neighbor_entry(thrift_neighbor_entry, &neighbor_entry);
      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parse_neighbor_attributes(thrift_attr_list, attr_list);
      uint32_t attr_count = thrift_attr_list.size();
      status = neighbor_api->create_neighbor_entry(&neighbor_entry, attr_count, attr_list);
      free(attr_list);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to create neighbor entry, status:%d", status);
      }
      return status;
  }

  sai_thrift_status_t sai_thrift_remove_neighbor_entry(const sai_thrift_neighbor_entry_t& thrift_neighbor_entry) {
    printf("sai_thrift_remove_neighbor_entry\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_neighbor_api_t *neighbor_api;
      sai_neighbor_entry_t neighbor_entry;
      status = sai_api_query(SAI_API_NEIGHBOR, (void **) &neighbor_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_thrift_parse_neighbor_entry(thrift_neighbor_entry, &neighbor_entry);
      status = neighbor_api->remove_neighbor_entry(&neighbor_entry);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to remove neighbor entry, status:%d", status);
      }
      return status;
  }

  sai_thrift_status_t sai_thrift_remove_all_neighbor_entry(void) {
    printf("sai_thrift_remove_all_neighbor_entry\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_neighbor_api_t *neighbor_api;
      sai_neighbor_entry_t neighbor_entry;
      status = sai_api_query(SAI_API_NEIGHBOR, (void **) &neighbor_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      status = neighbor_api->remove_all_neighbor_entries(gSwitchId);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to remove all neighbor entry, status:%d", status);
      }
      return status;
  }

sai_thrift_status_t sai_thrift_set_neighbor_entry_attribute(const sai_thrift_neighbor_entry_t& thrift_neighbor_entry, const sai_thrift_attribute_t& thrift_attr) {
      printf("sai_thrift_set_neighbor_entry_attribute\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };
      sai_neighbor_api_t *neighbor_api;
      sai_neighbor_entry_t neighbor_entry;
      sai_attribute_t *attr_list = nullptr;

      status = sai_api_query(SAI_API_NEIGHBOR, (void **) &neighbor_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_thrift_alloc_attr(attr_list, 1);
      sai_thrift_parse_neighbor_entry(thrift_neighbor_entry, &neighbor_entry);
      sai_thrift_parse_neighbor_attributes(thrift_attr_list, attr_list);
      status = neighbor_api->set_neighbor_entry_attribute(&neighbor_entry, attr_list);
      sai_thrift_free_attr(attr_list);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to set neighbor attributes, status:%d", status);
      }
      return status;
  }

void sai_thrift_get_neighbor_entry_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_neighbor_entry_t& thrift_neighbor_entry)
{
    printf("sai_thrift_get_neighbor_entry_attribute\n");
    sai_status_t status = SAI_STATUS_SUCCESS;
    sai_neighbor_api_t *neighbor_api;
    sai_neighbor_entry_t neighbor_entry;
    sai_attribute_t attr[SAI_NEIGHBOR_ENTRY_ATTR_END];
    sai_thrift_attribute_t thrift_attr;
    uint32_t attr_cnt = 0;

    status = sai_api_query(SAI_API_NEIGHBOR, (void **) &neighbor_api);
    if (status != SAI_STATUS_SUCCESS)
    {
        thrift_attr_list.status = status;
        return;
    }

    sai_thrift_parse_neighbor_entry(thrift_neighbor_entry, &neighbor_entry);

    attr[attr_cnt++].id = SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS;
    attr[attr_cnt++].id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION;
    attr[attr_cnt++].id = SAI_NEIGHBOR_ENTRY_ATTR_NO_HOST_ROUTE;

    status = neighbor_api->get_neighbor_entry_attribute(&neighbor_entry, attr_cnt, attr);
    if (status != SAI_STATUS_SUCCESS)
    {
        SAI_THRIFT_LOG_ERR("Failed to get neighbor attributes, status:%d", status);
        thrift_attr_list.status = status;
        return;
    }

    thrift_attr.id        = attr[0].id;
    thrift_attr.value.mac = sai_thrift_mac_to_string(attr[0].value.mac);
    thrift_attr_list.attr_list.push_back(thrift_attr);

    thrift_attr.id        = attr[1].id;
    thrift_attr.value.s32 = attr[1].value.s32;
    thrift_attr_list.attr_list.push_back(thrift_attr);

    thrift_attr.id        = attr[2].id;
    thrift_attr.value.booldata = attr[2].value.booldata;
    thrift_attr_list.attr_list.push_back(thrift_attr);

}

  sai_thrift_object_id_t sai_thrift_get_cpu_port_id() {
      sai_status_t status;
      sai_attribute_t attr;
      sai_switch_api_t *switch_api;
      sai_thrift_object_id_t cpu_port_id;
      const char* f_name = __FUNCTION__;
      printf("%s\n", f_name);
      status = sai_api_query(SAI_API_SWITCH, (void **) &switch_api);
      if (status != SAI_STATUS_SUCCESS) {
          printf("%s failed to obtain switch_api, status:%d\n", f_name, status);
          return SAI_NULL_OBJECT_ID;
      }
      attr.id = SAI_SWITCH_ATTR_CPU_PORT;
      status = switch_api->get_switch_attribute(gSwitchId, 1, &attr);
      if (status != SAI_STATUS_SUCCESS)
      {
          printf("%s failed, status:%d\n", f_name, status);
          return SAI_NULL_OBJECT_ID;
      }
      cpu_port_id = (sai_thrift_object_id_t) attr.value.oid;
      return cpu_port_id;
  }

  sai_thrift_object_id_t sai_thrift_get_default_router_id() {
      sai_status_t status;
      sai_attribute_t attr;
      sai_switch_api_t *switch_api;
      sai_thrift_object_id_t default_router_id;
      const char* f_name = __FUNCTION__;
      printf("%s\n", f_name);
      status = sai_api_query(SAI_API_SWITCH, (void **) &switch_api);
      if (status != SAI_STATUS_SUCCESS) {
          printf("%s failed to obtain switch_api, status:%d\n", f_name, status);
          return SAI_NULL_OBJECT_ID;
      }
      attr.id = SAI_SWITCH_ATTR_DEFAULT_VIRTUAL_ROUTER_ID;
      status = switch_api->get_switch_attribute(gSwitchId, 1, &attr);
      if (status != SAI_STATUS_SUCCESS)
      {
          printf("%s. Failed to get switch virtual router ID, status %d", f_name, status);
          return SAI_NULL_OBJECT_ID;
      }
      default_router_id = (sai_thrift_object_id_t)attr.value.oid;
      return default_router_id;
  }

  sai_thrift_object_id_t sai_thrift_get_default_1q_bridge_id()
  {
      sai_switch_api_t *switch_api;
      sai_attribute_t attr;
      sai_status_t status;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_SWITCH, (void **) &switch_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain switch_api, status:%d\n", status);
          return SAI_NULL_OBJECT_ID;
      }

      attr.id = SAI_SWITCH_ATTR_DEFAULT_1Q_BRIDGE_ID;
      status = switch_api->get_switch_attribute(gSwitchId, 1, &attr);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to get switch virtual router ID, status %d", status);
          return SAI_NULL_OBJECT_ID;
      }

      return (sai_thrift_object_id_t)attr.value.oid;
  }

  void sai_thrift_get_default_vlan_id(sai_thrift_result_t &ret) {
      sai_switch_api_t *switch_api;
      sai_attribute_t attr;

      SAI_THRIFT_FUNC_LOG();

      ret.status = sai_api_query(SAI_API_SWITCH, (void **) &switch_api);
      if (ret.status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain switch_api, status:%d", ret.status);
          return;
      }

      attr.id = SAI_SWITCH_ATTR_DEFAULT_VLAN_ID;
      ret.status = switch_api->get_switch_attribute(gSwitchId, 1, &attr);
      if (ret.status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("failed to get switch default vlan ID, status:%d", ret.status);
          return;
      }

      ret.data.oid = (sai_thrift_object_id_t)attr.value.oid;
  }

  sai_thrift_object_id_t sai_thrift_get_default_trap_group() {
      sai_status_t status;
      sai_attribute_t attr;
      sai_switch_api_t *switch_api;
      sai_thrift_object_id_t default_trap_group;
      const char* f_name = __FUNCTION__;
      printf("%s\n", f_name);
      status = sai_api_query(SAI_API_SWITCH, (void **) &switch_api);
      if (status != SAI_STATUS_SUCCESS) {
          printf("%s failed to obtain switch_api, status:%d\n", f_name, status);
          return SAI_NULL_OBJECT_ID;
      }
      attr.id = SAI_SWITCH_ATTR_DEFAULT_TRAP_GROUP;
      status = switch_api->get_switch_attribute(gSwitchId, 1, &attr);
      if (status != SAI_STATUS_SUCCESS)
      {
          printf("%s. Failed to get switch default trap group, status %d", f_name, status);
          return SAI_NULL_OBJECT_ID;
      }
      default_trap_group = (sai_thrift_object_id_t)attr.value.oid;
      return default_trap_group;
  }

  sai_thrift_object_id_t sai_thrift_create_switch(void) {
      printf("sai_thrift_create_switch\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_switch_api_t *sai_switch_api;
      constexpr std::uint32_t attrSz = 1;
      sai_attribute_t attr[attrSz];
      extern void handleProfileMap(const std::string& profileMapFile);

      handleProfileMap("profile.ini");
      status = sai_api_query(SAI_API_SWITCH, (void **) &sai_switch_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      std :: memset(attr, '\0', sizeof(attr));
      attr[0].id = SAI_SWITCH_ATTR_INIT_SWITCH;
      attr[0].value.booldata = true;

      sai_switch_api->create_switch(&gSwitchId, attrSz, attr);

      return gSwitchId;
  }

  sai_thrift_status_t sai_thrift_remove_switch(void) {
      printf("sai_thrift_remove_switch\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_switch_api_t *sai_switch_api;
      status = sai_api_query(SAI_API_SWITCH, (void **) &sai_switch_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      status = sai_switch_api->remove_switch((sai_object_id_t)gSwitchId);
      return status;
  }

# if 0
  void sai_thrift_get_switch_attribute(sai_thrift_attribute_list_t& thrift_attr_list) {
      printf("sai_thrift_get_switch_attribute\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_switch_api_t *switch_api;
      sai_attribute_t max_port_attribute;
      sai_attribute_t port_list_object_attribute;
      sai_thrift_attribute_t thrift_port_list_attribute;
      sai_object_list_t *port_list_object;
      int max_ports = 0;
	  sai_attribute_t attr;
	  sai_thrift_attribute_t thrift_attr;
      status = sai_api_query(SAI_API_SWITCH, (void **) &switch_api);
      if (status != SAI_STATUS_SUCCESS) {
          printf("sai_api_query failed!!!\n");
          return;
      }

      max_port_attribute.id = SAI_SWITCH_ATTR_PORT_NUMBER;
      switch_api->get_switch_attribute(gSwitchId, 1, &max_port_attribute);
      max_ports = max_port_attribute.value.u32;
      port_list_object_attribute.id = SAI_SWITCH_ATTR_PORT_LIST;
      port_list_object_attribute.value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * max_ports);
      port_list_object_attribute.value.objlist.count = max_ports;
      switch_api->get_switch_attribute(gSwitchId, 1, &port_list_object_attribute);

	  attr.id = SAI_SWITCH_ATTR_QOS_DEFAULT_TC;
	  switch_api->get_switch_attribute(gSwitchId, 1, &attr);
      thrift_attr_list.attr_count = 0;
      std::vector<sai_thrift_attribute_t>& attr_list = thrift_attr_list.attr_list;
      thrift_port_list_attribute.id = SAI_SWITCH_ATTR_PORT_LIST;
      thrift_port_list_attribute.value.objlist.count = max_ports;
      std::vector<sai_thrift_object_id_t>& port_list = thrift_port_list_attribute.value.objlist.object_id_list;
      port_list_object = &port_list_object_attribute.value.objlist;
      for (int index = 0; index < max_ports; index++) {
          port_list.push_back((sai_thrift_object_id_t) port_list_object->list[index]);
      }
      attr_list.push_back(thrift_port_list_attribute);
	  thrift_attr.id = attr.id;
	  thrift_attr.value.u8 = attr.value.u8;
	  attr_list.push_back(thrift_attr);
      free(port_list_object_attribute.value.objlist.list);
  }
#endif
  void sai_thrift_convert_to_switch_thrift_attributes(
          sai_attribute_t *attr_list,
          uint32_t attr_count,
          sai_thrift_attribute_list_t& thrift_attr_list)
          {
              sai_attribute_t attribute;
              sai_thrift_attribute_t thrift_attr;

              for (uint32_t i = 0; i < attr_count; i++)
              {
                  attribute = attr_list[i];
                  switch (attribute.id)
                  {   /* sai_uint32_t */
                      case SAI_SWITCH_ATTR_PORT_NUMBER:
                      case SAI_SWITCH_ATTR_MAX_NUMBER_OF_SUPPORTED_PORTS:
                      case SAI_SWITCH_ATTR_PORT_MAX_MTU:
                      case SAI_SWITCH_ATTR_MAX_VIRTUAL_ROUTERS:
                      case SAI_SWITCH_ATTR_FDB_TABLE_SIZE:
                      case SAI_SWITCH_ATTR_L3_NEIGHBOR_TABLE_SIZE:
                      case SAI_SWITCH_ATTR_L3_ROUTE_TABLE_SIZE:
                      case SAI_SWITCH_ATTR_LAG_MEMBERS:
                      case SAI_SWITCH_ATTR_NUMBER_OF_LAGS:
                      case SAI_SWITCH_ATTR_ECMP_MEMBERS:
                      case SAI_SWITCH_ATTR_NUMBER_OF_ECMP_GROUPS:
                      case SAI_SWITCH_ATTR_NUMBER_OF_UNICAST_QUEUES:
                      case SAI_SWITCH_ATTR_NUMBER_OF_MULTICAST_QUEUES:
                      case SAI_SWITCH_ATTR_NUMBER_OF_QUEUES:
                      case SAI_SWITCH_ATTR_NUMBER_OF_CPU_QUEUES:
                      case SAI_SWITCH_ATTR_ACL_TABLE_MINIMUM_PRIORITY:
                      case SAI_SWITCH_ATTR_ACL_TABLE_MAXIMUM_PRIORITY:
                      case SAI_SWITCH_ATTR_ACL_ENTRY_MINIMUM_PRIORITY:
                      case SAI_SWITCH_ATTR_ACL_ENTRY_MAXIMUM_PRIORITY:
                      case SAI_SWITCH_ATTR_ACL_TABLE_GROUP_MINIMUM_PRIORITY:
                      case SAI_SWITCH_ATTR_ACL_TABLE_GROUP_MAXIMUM_PRIORITY:
                      case SAI_SWITCH_ATTR_QOS_MAX_NUMBER_OF_SCHEDULER_GROUP_HIERARCHY_LEVELS:
                      case SAI_SWITCH_ATTR_QOS_MAX_NUMBER_OF_CHILDS_PER_SCHEDULER_GROUP:
                      case SAI_SWITCH_ATTR_TOTAL_BUFFER_SIZE:
                      case SAI_SWITCH_ATTR_INGRESS_BUFFER_POOL_NUM:
                      case SAI_SWITCH_ATTR_EGRESS_BUFFER_POOL_NUM:
                      case SAI_SWITCH_ATTR_AVAILABLE_IPV4_ROUTE_ENTRY:
                      case SAI_SWITCH_ATTR_AVAILABLE_IPV6_ROUTE_ENTRY:
                      case SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEXTHOP_ENTRY:
                      case SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEXTHOP_ENTRY:
                      case SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEIGHBOR_ENTRY:
                      case SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEIGHBOR_ENTRY:
                      case SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_ENTRY:
                      case SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_MEMBER_ENTRY:
                      case SAI_SWITCH_ATTR_AVAILABLE_FDB_ENTRY:
                      case SAI_SWITCH_ATTR_AVAILABLE_L2MC_ENTRY:
                      case SAI_SWITCH_ATTR_AVAILABLE_IPMC_ENTRY:
                      case SAI_SWITCH_ATTR_MIN_PLANNED_RESTART_INTERVAL:
                      case SAI_SWITCH_ATTR_MAX_ACL_ACTION_COUNT:
                      case SAI_SWITCH_ATTR_MAX_ACL_RANGE_COUNT:
                      case SAI_SWITCH_ATTR_MAX_LEARNED_ADDRESSES:
                      case SAI_SWITCH_ATTR_FDB_AGING_TIME:
                      case SAI_SWITCH_ATTR_ECMP_DEFAULT_HASH_SEED:
                      case SAI_SWITCH_ATTR_LAG_DEFAULT_HASH_SEED:
                      case SAI_SWITCH_ATTR_COUNTER_REFRESH_INTERVAL:
                      case SAI_SWITCH_ATTR_SWITCH_PROFILE_ID:
                      case SAI_SWITCH_ATTR_SEGMENTROUTE_MAX_SID_DEPTH:
                      case SAI_SWITCH_ATTR_QOS_NUM_LOSSLESS_QUEUES:
                          thrift_attr.id        = attribute.id;
                          thrift_attr.value.u32 = attribute.value.u32;
                          thrift_attr_list.attr_list.push_back(thrift_attr);
                          break;
                          /* s32 */
                      case SAI_SWITCH_ATTR_OPER_STATUS:
                      case SAI_SWITCH_ATTR_RESTART_TYPE:
                      case SAI_SWITCH_ATTR_MCAST_SNOOPING_CAPABILITY:
                      case SAI_SWITCH_ATTR_SWITCHING_MODE:
                      case SAI_SWITCH_ATTR_FDB_UNICAST_MISS_PACKET_ACTION:
                      case SAI_SWITCH_ATTR_FDB_BROADCAST_MISS_PACKET_ACTION:
                      case SAI_SWITCH_ATTR_FDB_MULTICAST_MISS_PACKET_ACTION:
                      case SAI_SWITCH_ATTR_ECMP_DEFAULT_HASH_ALGORITHM:
                      case SAI_SWITCH_ATTR_LAG_DEFAULT_HASH_ALGORITHM:
                      case SAI_SWITCH_ATTR_PFC_DLR_PACKET_ACTION:
                          thrift_attr.id        = attribute.id;
                          thrift_attr.value.s32 = attribute.value.s32;
                          thrift_attr_list.attr_list.push_back(thrift_attr);
                          break;
                          /* sai_uint16_t */
                      case SAI_SWITCH_ATTR_TPID_OUTER_VLAN:
                      case SAI_SWITCH_ATTR_TPID_INNER_VLAN:
                          thrift_attr.id        = attribute.id;
                          thrift_attr.value.s32 = attribute.value.s32;
                          thrift_attr_list.attr_list.push_back(thrift_attr);
                          break;
                          /* sai_uint8_t */
                      case SAI_SWITCH_ATTR_QOS_MAX_NUMBER_OF_TRAFFIC_CLASSES:
                      case SAI_SWITCH_ATTR_QOS_DEFAULT_TC:
                      case SAI_SWITCH_ATTR_MIRROR_TC:
                          thrift_attr.id        = attribute.id;
                          thrift_attr.value.u8 = attribute.value.u8;
                          thrift_attr_list.attr_list.push_back(thrift_attr);
                          break;
                          /* sai_object_id_t */
                      case SAI_SWITCH_ATTR_CPU_PORT:
                      case SAI_SWITCH_ATTR_DEFAULT_VLAN_ID:
                      case SAI_SWITCH_ATTR_DEFAULT_STP_INST_ID:
                      case SAI_SWITCH_ATTR_DEFAULT_VIRTUAL_ROUTER_ID:
                      case SAI_SWITCH_ATTR_DEFAULT_1Q_BRIDGE_ID:
                      case SAI_SWITCH_ATTR_INGRESS_ACL:
                      case SAI_SWITCH_ATTR_EGRESS_ACL:
                      case SAI_SWITCH_ATTR_DEFAULT_TRAP_GROUP:
                      case SAI_SWITCH_ATTR_ECMP_HASH:
                      case SAI_SWITCH_ATTR_LAG_HASH:
                      case SAI_SWITCH_ATTR_ECMP_HASH_IPV4:
                      case SAI_SWITCH_ATTR_ECMP_HASH_IPV4_IN_IPV4:
                      case SAI_SWITCH_ATTR_ECMP_HASH_IPV6:
                      case SAI_SWITCH_ATTR_LAG_HASH_IPV4:
                      case SAI_SWITCH_ATTR_LAG_HASH_IPV4_IN_IPV4:
                      case SAI_SWITCH_ATTR_LAG_HASH_IPV6:
                      case SAI_SWITCH_ATTR_QOS_DOT1P_TO_TC_MAP:
                      case SAI_SWITCH_ATTR_QOS_DOT1P_TO_COLOR_MAP:
                      case SAI_SWITCH_ATTR_QOS_DSCP_TO_TC_MAP:
                      case SAI_SWITCH_ATTR_QOS_DSCP_TO_COLOR_MAP:
                      case SAI_SWITCH_ATTR_QOS_TC_TO_QUEUE_MAP:
                      case SAI_SWITCH_ATTR_QOS_TC_AND_COLOR_TO_DOT1P_MAP:
                      case SAI_SWITCH_ATTR_QOS_TC_AND_COLOR_TO_DSCP_MAP:
                          thrift_attr.id        = attribute.id;
                          thrift_attr.value.oid = attribute.value.oid;
                          thrift_attr_list.attr_list.push_back(thrift_attr);
                          break;
                          /* sai_uint64_t */
                      case SAI_SWITCH_ATTR_NV_STORAGE_SIZE:
                          thrift_attr.id        = attribute.id;
                          thrift_attr.value.u64 = attribute.value.u64;
                          thrift_attr_list.attr_list.push_back(thrift_attr);
                          break;
                          /* bool */
                      case SAI_SWITCH_ATTR_ON_LINK_ROUTE_SUPPORTED:
                      case SAI_SWITCH_ATTR_RESTART_WARM:
                      case SAI_SWITCH_ATTR_BCAST_CPU_FLOOD_ENABLE:
                      case SAI_SWITCH_ATTR_MCAST_CPU_FLOOD_ENABLE:
                      case SAI_SWITCH_ATTR_ECMP_DEFAULT_SYMMETRIC_HASH:
                      case SAI_SWITCH_ATTR_LAG_DEFAULT_SYMMETRIC_HASH:
                      case SAI_SWITCH_ATTR_SWITCH_SHELL_ENABLE:
                      case SAI_SWITCH_ATTR_INIT_SWITCH:
                      case SAI_SWITCH_ATTR_FAST_API_ENABLE:
					  case SAI_SWITCH_ATTR_UNINIT_DATA_PLANE_ON_REMOVAL:
                          thrift_attr.id        = attribute.id;
                          thrift_attr.value.booldata = attribute.value.booldata;
                          thrift_attr_list.attr_list.push_back(thrift_attr);
                          break;
                          /* sai_u32_range_t */
                      case SAI_SWITCH_ATTR_FDB_DST_USER_META_DATA_RANGE:
                      case SAI_SWITCH_ATTR_ROUTE_DST_USER_META_DATA_RANGE:
                      case SAI_SWITCH_ATTR_NEIGHBOR_DST_USER_META_DATA_RANGE:
                      case SAI_SWITCH_ATTR_PORT_USER_META_DATA_RANGE:
                      case SAI_SWITCH_ATTR_VLAN_USER_META_DATA_RANGE:
                      case SAI_SWITCH_ATTR_ACL_USER_META_DATA_RANGE:
                      case SAI_SWITCH_ATTR_ACL_USER_TRAP_ID_RANGE:
                      case SAI_SWITCH_ATTR_PFC_TC_DLD_INTERVAL_RANGE:
                      case SAI_SWITCH_ATTR_PFC_TC_DLR_INTERVAL_RANGE:
                          break;
                          /* sai_int32_t */
                      case SAI_SWITCH_ATTR_MAX_TEMP:
                          thrift_attr.id        = attribute.id;
                          thrift_attr.value.booldata = attribute.value.booldata;
                          thrift_attr_list.attr_list.push_back(thrift_attr);
                          break;
                          /* sai_object_list_t */
                      case SAI_SWITCH_ATTR_PORT_LIST:
                          {
                              thrift_attr.id        = attribute.id;
                              thrift_attr.value.objlist.count = attribute.value.objlist.count;
                              std::vector < sai_thrift_object_id_t > & port_list = thrift_attr.value.objlist.object_id_list;
                              //std::vector < sai_int8_t > & udf_list = thrift_attr.value.u8list.u8list;
                              for (int index = 0; index < attribute.value.objlist.count; index++)
                              {
                                  port_list.push_back((sai_thrift_object_id_t)attribute.value.objlist.list[index]);
                              }
                              thrift_attr_list.attr_list.push_back(thrift_attr);
                              break;
                          }
                          /* sai_u32_list_t */
                      case SAI_SWITCH_ATTR_QOS_MAX_NUMBER_OF_SCHEDULER_GROUPS_PER_HIERARCHY_LEVEL:
                          {
                              thrift_attr.id        = attribute.id;
                              thrift_attr.value.u32list.count = attribute.value.u32list.count;
                              //std::vector < sai_uint32_t > & qos_member_list = thrift_attr.value.u32list.u32list;
                              std :: vector < sai_int32_t > & qos_member_list = thrift_attr.value.u32list.u32list;
                              for (int index = 0; index < attribute.value.u32list.count; index++)
                              {
                                  //qos_member_list.push_back((sai_uint32_t)attribute.value.u32list.list[index]);
                                  qos_member_list.push_back((sai_int32_t)attribute.value.u32list.list[index]);
                              }
                              // memcpy(thrift_attr.value.u32list.u32list, attribute.value.u32list.list, sizeof(sai_uint32_t)*attribute.value.u32list.count);
                              thrift_attr_list.attr_list.push_back(thrift_attr);
                              break;
                          }
                          /* sai_s32_list_t */
                      case SAI_SWITCH_ATTR_SEGMENTROUTE_TLV_TYPE:
                      case SAI_SWITCH_ATTR_SUPPORTED_PROTECTED_OBJECT_TYPE:
                          {
                              thrift_attr.id        = attribute.id;
                              thrift_attr.value.s32list.count = attribute.value.s32list.count;
                              std::vector < sai_int32_t > & s32_data_list = thrift_attr.value.s32list.s32list;
                              for (int index = 0; index < attribute.value.s32list.count; index++)
                              {
                                  s32_data_list.push_back((sai_int32_t)attribute.value.s32list.list[index]);
                              }
                              thrift_attr_list.attr_list.push_back(thrift_attr);
                              break;
                          }
                          /* sai_s8_list_t */
                      case SAI_SWITCH_ATTR_SWITCH_HARDWARE_INFO:
                      case SAI_SWITCH_ATTR_FIRMWARE_PATH_NAME:
                          {
                              thrift_attr.id        = attribute.id;
                              thrift_attr.value.s8list.count = attribute.value.s8list.count;
                              std::vector < sai_int8_t > & s8_data_list = thrift_attr.value.s8list.s8list;
                              for (int index = 0; index < attribute.value.s8list.count; index++)
                              {
                                  s8_data_list.push_back((sai_int8_t)attribute.value.s8list.list[index]);
                              }
                              thrift_attr_list.attr_list.push_back(thrift_attr);
                              break;
                          }
                          /* sai_map_list_t */
                      case SAI_SWITCH_ATTR_PFC_TC_DLD_INTERVAL:
                      case SAI_SWITCH_ATTR_PFC_TC_DLR_INTERVAL:
                          break;

                          /* sai_acl_resource_list_t */
                      case SAI_SWITCH_ATTR_AVAILABLE_ACL_TABLE:
                      case SAI_SWITCH_ATTR_AVAILABLE_ACL_TABLE_GROUP:
                          break;

                          /* sai_acl_capability_t */
                      case SAI_SWITCH_ATTR_ACL_CAPABILITY:
                      case SAI_SWITCH_ATTR_ACL_STAGE_INGRESS:
                      case SAI_SWITCH_ATTR_ACL_STAGE_EGRESS:
                          break;
                          /* sai_mac_t */
                      case SAI_SWITCH_ATTR_SRC_MAC_ADDRESS:
                          break;

                          /* sai_pointer_t(no need to process) */
                      case SAI_SWITCH_ATTR_SWITCH_STATE_CHANGE_NOTIFY:
                      case SAI_SWITCH_ATTR_SWITCH_SHUTDOWN_REQUEST_NOTIFY:
                      case SAI_SWITCH_ATTR_FDB_EVENT_NOTIFY:
                      case SAI_SWITCH_ATTR_PORT_STATE_CHANGE_NOTIFY:
                      case SAI_SWITCH_ATTR_PACKET_EVENT_NOTIFY:
                      case SAI_SWITCH_ATTR_TAM_EVENT_NOTIFY:
                      case SAI_SWITCH_ATTR_QUEUE_PFC_DEADLOCK_NOTIFY:
                          break;
                  }
              }
              return;
          }


	void sai_thrift_get_switch_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const std::vector < int32_t > & thrift_attr_ids)
	{
        printf("sai_thrift_get_switch_attribute\n");
        sai_status_t status = SAI_STATUS_SUCCESS;
        sai_switch_api_t *switch_api;
        sai_attribute_t max_port_attribute;
		sai_attribute_t sai_attribute;
        uint32_t max_ports = 0;

		memset(&max_port_attribute, 0, sizeof(sai_attribute_t));
		memset(&sai_attribute, 0, sizeof(sai_attribute_t));
        status = sai_api_query(SAI_API_SWITCH, (void **) &switch_api);
        if (status != SAI_STATUS_SUCCESS)
        {
            printf("sai_api_query failed!!!\n");
            return;
        }

        uint32_t attr_count = thrift_attr_ids.size();
        sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_ids.size());
        memset(attr_list, 0x0, sizeof(sizeof(sai_attribute_t) * thrift_attr_ids.size()));
        sai_thrift_parse_attribute_ids(thrift_attr_ids, attr_list);

        for (uint32_t i = 0; i < attr_count; i++)
      {
          switch(attr_list[i].id)
          {
          case SAI_SWITCH_ATTR_PORT_LIST:  /* sai_object_list_t */
              /* malloc list for SAI_SWITCH_ATTR_PORT_LIST */
              max_port_attribute.id = SAI_SWITCH_ATTR_PORT_NUMBER;
              switch_api->get_switch_attribute(gSwitchId, 1, &max_port_attribute);
              max_ports = max_port_attribute.value.u32;
              attr_list[i].value.objlist.list = (uint64_t *) malloc(sizeof(uint64_t) * max_ports);
              attr_list[i].value.objlist.count = max_ports;
              break;
          case SAI_SWITCH_ATTR_QOS_MAX_NUMBER_OF_SCHEDULER_GROUPS_PER_HIERARCHY_LEVEL: /* sai_u32_list_t */
              attr_list[i].value.u32list.list = (uint32_t *) malloc(sizeof(uint32_t) * CNT_UNSUPPORT); /* how much? ===>> unsupport */
              attr_list[i].value.u32list.count = CNT_UNSUPPORT;
              break;
          case SAI_SWITCH_ATTR_SEGMENTROUTE_TLV_TYPE:/* sai_s32_list_t */
              attr_list[i].value.s32list.list = (int32_t *) malloc(sizeof(int32_t) * CNT_UNSUPPORT);
              attr_list[i].value.s32list.count = CNT_UNSUPPORT;
              break;
          case SAI_SWITCH_ATTR_SUPPORTED_PROTECTED_OBJECT_TYPE:/* sai_s32_list_t */
              attr_list[i].value.s32list.list = (int32_t *) malloc(sizeof(int32_t) * CNT_UNSUPPORT);
              attr_list[i].value.s32list.count = CNT_UNSUPPORT;
              break;
          case SAI_SWITCH_ATTR_SWITCH_HARDWARE_INFO:/* sai_s8_list_t */
              attr_list[i].value.s8list.list = (int8_t *) malloc(sizeof(int8_t) * 10);   /* unknown */
              attr_list[i].value.s8list.count = 10;
              break;
          case SAI_SWITCH_ATTR_FIRMWARE_PATH_NAME:/* sai_s8_list_t */
              attr_list[i].value.s8list.list = (int8_t *) malloc(sizeof(int8_t) * 10);   /* unknown */
              attr_list[i].value.s8list.count = 10;
              break;
          case SAI_SWITCH_ATTR_PFC_TC_DLD_INTERVAL:/* sai_map_list_t */
              break;
          case SAI_SWITCH_ATTR_PFC_TC_DLR_INTERVAL:/* sai_map_list_t */
              break;
          case SAI_SWITCH_ATTR_AVAILABLE_ACL_TABLE:/* sai_acl_resource_list_t */
              break;
          case SAI_SWITCH_ATTR_AVAILABLE_ACL_TABLE_GROUP:/* sai_acl_resource_list_t */
              break;
          case SAI_SWITCH_ATTR_ACL_CAPABILITY:/* sai_acl_capability_t */
              break;
          case SAI_SWITCH_ATTR_ACL_STAGE_INGRESS:/* sai_acl_capability_t */
              break;
          case SAI_SWITCH_ATTR_ACL_STAGE_EGRESS:/* sai_acl_capability_t */
              break;
          case SAI_SWITCH_ATTR_SRC_MAC_ADDRESS:/* sai_mac_t */
              break;
		  case SAI_SWITCH_ATTR_UNINIT_DATA_PLANE_ON_REMOVAL:
              sai_attribute.id = SAI_SWITCH_ATTR_UNINIT_DATA_PLANE_ON_REMOVAL;
              switch_api->get_switch_attribute(gSwitchId, 1, &sai_attribute);
              attr_list[i].value.booldata = sai_attribute.value.booldata;
              break;
          default:
              break;
          }
      }

	  status = switch_api->get_switch_attribute(gSwitchId, attr_count, attr_list);
	  if (status != SAI_STATUS_SUCCESS)
	  {
          SAI_THRIFT_LOG_ERR("Failed to get switch attributes, status:%d", status);
          thrift_attr_list.status = status;
          return;
      }

	  sai_thrift_convert_to_switch_thrift_attributes(
	                                                  attr_list,
	                                                  attr_count,
	                                                  thrift_attr_list);

	  for (uint32_t i = 0; i < attr_count; i++)
      {
          if ((SAI_SWITCH_ATTR_PORT_LIST == attr_list[i].id) && (attr_list[i].value.objlist.list))
          {
              free(attr_list[i].value.objlist.list);
          }
          if ((SAI_SWITCH_ATTR_QOS_MAX_NUMBER_OF_SCHEDULER_GROUPS_PER_HIERARCHY_LEVEL == attr_list[i].id) && (attr_list[i].value.u32list.list))
          {
              free(attr_list[i].value.u32list.list);
          }
          if ((SAI_SWITCH_ATTR_SEGMENTROUTE_TLV_TYPE == attr_list[i].id) && (attr_list[i].value.s32list.list))
          {
              free(attr_list[i].value.s32list.list);
          }
          if ((SAI_SWITCH_ATTR_SUPPORTED_PROTECTED_OBJECT_TYPE == attr_list[i].id) && (attr_list[i].value.s32list.list))
          {
              free(attr_list[i].value.s32list.list);
          }
          if ((SAI_SWITCH_ATTR_SWITCH_HARDWARE_INFO == attr_list[i].id) && (attr_list[i].value.u8list.list))
          {
              free(attr_list[i].value.u8list.list);
          }
          if ((SAI_SWITCH_ATTR_FIRMWARE_PATH_NAME == attr_list[i].id) && (attr_list[i].value.u8list.list))
          {
              free(attr_list[i].value.u8list.list);
          }
      }
 	  if(attr_list)
 	  {
 	      free(attr_list);
 	  }
	  return;
	}

  sai_thrift_status_t sai_thrift_set_switch_attribute(const sai_thrift_attribute_t& thrift_attr) {
      printf("sai_thrift_set_switch_attribute\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_switch_api_t *switch_api;
      sai_attribute_t attr;
	  memset(&attr, 0, sizeof(sai_attribute_t));
      status = sai_api_query(SAI_API_SWITCH, (void **) &switch_api);
      if (status != SAI_STATUS_SUCCESS) {
          printf("sai_api_query failed!!!\n");
          return status;
      }

      sai_thrift_parse_switch_attribute(thrift_attr, &attr);

      status = switch_api->set_switch_attribute(gSwitchId, &attr);
	  if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to set switch attributes, status:%d", status);
      }
      return status;
  }

  void sai_thrift_parse_switch_attribute(const sai_thrift_attribute_t &thrift_attr, sai_attribute_t *attr) {
      attr->id = thrift_attr.id;

      switch(thrift_attr.id) {
          case SAI_SWITCH_ATTR_SRC_MAC_ADDRESS:
              sai_thrift_string_to_mac(thrift_attr.value.mac, attr->value.mac);
              break;

          case SAI_SWITCH_ATTR_FDB_UNICAST_MISS_PACKET_ACTION:
          case SAI_SWITCH_ATTR_FDB_BROADCAST_MISS_PACKET_ACTION:
          case SAI_SWITCH_ATTR_FDB_MULTICAST_MISS_PACKET_ACTION:
              attr->value.s32 = thrift_attr.value.s32;
              break;
          case SAI_SWITCH_ATTR_FDB_AGING_TIME:
              attr->value.u32 = thrift_attr.value.u32;
              break;
          case SAI_SWITCH_ATTR_QOS_DEFAULT_TC:
              attr->value.u8 = thrift_attr.value.u8;
              break;
          case SAI_SWITCH_ATTR_QOS_TC_TO_QUEUE_MAP:
          case SAI_SWITCH_ATTR_QOS_DOT1P_TO_TC_MAP:
          case SAI_SWITCH_ATTR_QOS_DOT1P_TO_COLOR_MAP:
          case SAI_SWITCH_ATTR_QOS_DSCP_TO_TC_MAP:
          case SAI_SWITCH_ATTR_QOS_DSCP_TO_COLOR_MAP:
          case SAI_SWITCH_ATTR_QOS_TC_AND_COLOR_TO_DOT1P_MAP:
          case SAI_SWITCH_ATTR_QOS_TC_AND_COLOR_TO_DSCP_MAP:
		  case SAI_SWITCH_ATTR_INGRESS_ACL:
              attr->value.oid = thrift_attr.value.oid;
              break;
          case SAI_SWITCH_ATTR_RESTART_WARM:
		  case SAI_SWITCH_ATTR_UNINIT_DATA_PLANE_ON_REMOVAL:
              attr->value.booldata = thrift_attr.value.booldata;
              break;
      }
  }

  void sai_thrift_get_port_list_by_front_port(sai_thrift_attribute_t& thrift_attr) {
      printf("sai_thrift_get_port_list_by_front_port\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_switch_api_t *switch_api;
      sai_port_api_t *port_api;
      sai_attribute_t max_port_attribute;
      sai_attribute_t port_list_object_attribute;
      sai_attribute_t port_lane_list_attribute;
      sai_thrift_attribute_t thrift_port_list_attribute;
      sai_object_list_t *port_list_object;
      int max_ports = 0;
      extern std::map<std::set<int>, std::string> gPortMap;
      std::map<std::set<int>, std::string>::iterator gPortMapIt;

      status = sai_api_query(SAI_API_SWITCH, (void **) &switch_api);
      if (status != SAI_STATUS_SUCCESS) {
          printf("sai_api_query failed!!!\n");
          return;
      }

      status = sai_api_query(SAI_API_PORT, (void **) &port_api);
      if (status != SAI_STATUS_SUCCESS) {
          printf("sai_api_query failed!!!\n");
          return;
      }

      max_port_attribute.id = SAI_SWITCH_ATTR_PORT_NUMBER;
      switch_api->get_switch_attribute(gSwitchId, 1, &max_port_attribute);
      max_ports = max_port_attribute.value.u32;
      port_list_object_attribute.id = SAI_SWITCH_ATTR_PORT_LIST;
      port_list_object_attribute.value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * max_ports);
      port_list_object_attribute.value.objlist.count = max_ports;
      switch_api->get_switch_attribute(gSwitchId, 1, &port_list_object_attribute);
      std::map<int, sai_object_id_t> front_to_sai_map;

      for (int i=0 ; i<max_ports ; i++){
          port_lane_list_attribute.id = SAI_PORT_ATTR_HW_LANE_LIST;
          port_lane_list_attribute.value.u32list.list = (uint32_t *) malloc(sizeof(uint32_t) * 4);
          port_lane_list_attribute.value.u32list.count = 4;
          port_api->get_port_attribute(port_list_object_attribute.value.objlist.list[i], 1, &port_lane_list_attribute);

          std::set<int> port_lanes;
          uint32_t laneCnt = port_lane_list_attribute.value.u32list.count;
          for (int j=0 ; j<laneCnt; j++){
              port_lanes.insert(port_lane_list_attribute.value.u32list.list[j]);
          }

          gPortMapIt = gPortMap.find(port_lanes);
          if (gPortMapIt != gPortMap.end()){
              std::string front_port_alias = gPortMapIt->second.c_str();
              std::string front_port_number;
              int front_num_to_sort=0;
              for (int k=0 ; k<front_port_alias.length() ; k++){
                  if (front_port_alias[k] >= '0' && front_port_alias[k] <= '9'){
                      front_port_number.push_back(front_port_alias[k]);
                  }
              }
              front_num_to_sort = std::stoi(front_port_number);
              front_to_sai_map.insert(std::pair<int,sai_object_id_t>(front_num_to_sort,port_list_object_attribute.value.objlist.list[i]));
          }
          else {
              printf("DIDN'T FOUND FRONT PORT FOR LANE SET\n");
          }
          free(port_lane_list_attribute.value.u32list.list);
      }

      sai_thrift_attribute_t& attr = thrift_attr;
      thrift_port_list_attribute.id = SAI_SWITCH_ATTR_PORT_LIST;
      thrift_port_list_attribute.value.objlist.count = max_ports;
      std::vector<sai_thrift_object_id_t>& port_list = thrift_port_list_attribute.value.objlist.object_id_list;
      for (std::map<int, sai_object_id_t>::iterator it = front_to_sai_map.begin() ; it != front_to_sai_map.end(); it++) {
          port_list.push_back((sai_thrift_object_id_t) it->second);
      }
      attr = thrift_port_list_attribute;
      free(port_list_object_attribute.value.objlist.list);
  }

  sai_thrift_object_id_t sai_thrift_get_port_id_by_front_port(const std::string& port_name) {
      printf("sai_thrift_get_port_id_by_front_port\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_switch_api_t *switch_api;
      sai_port_api_t *port_api;
      sai_attribute_t max_port_attribute;
      sai_attribute_t port_list_object_attribute;
      sai_attribute_t port_lane_list_attribute;
      sai_object_list_t *port_list_object;
      int max_ports = 0;
      sai_thrift_object_id_t port_id;
      extern std::map<std::set<int>, std::string> gPortMap;
      std::map<std::set<int>, std::string>::iterator gPortMapIt;

      status = sai_api_query(SAI_API_SWITCH, (void **) &switch_api);
      if (status != SAI_STATUS_SUCCESS) {
          printf("sai_api_query failed!!!\n");
          return SAI_NULL_OBJECT_ID;
      }
      status = sai_api_query(SAI_API_PORT, (void **) &port_api);
      if (status != SAI_STATUS_SUCCESS) {
          printf("sai_api_query failed!!!\n");
          return SAI_NULL_OBJECT_ID;
      }
      for (gPortMapIt = gPortMap.begin() ; gPortMapIt != gPortMap.end() ; gPortMapIt++){
          if (gPortMapIt->second == port_name){
              break;
          }
      }

      std::set<int> lane_set;
      if (gPortMapIt != gPortMap.end()){
          lane_set = gPortMapIt->first;
      }
      else {
          printf("Didn't find matching port to received name!\n");
          return SAI_NULL_OBJECT_ID;
      }

      max_port_attribute.id = SAI_SWITCH_ATTR_PORT_NUMBER;
      switch_api->get_switch_attribute(gSwitchId, 1, &max_port_attribute);
      max_ports = max_port_attribute.value.u32;
      port_list_object_attribute.id = SAI_SWITCH_ATTR_PORT_LIST;
      port_list_object_attribute.value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * max_ports);
      port_list_object_attribute.value.objlist.count = max_ports;
      switch_api->get_switch_attribute(gSwitchId, 1, &port_list_object_attribute);

      for (int i=0 ; i<max_ports ; i++){
          port_lane_list_attribute.id = SAI_PORT_ATTR_HW_LANE_LIST;
          port_lane_list_attribute.value.u32list.list = (uint32_t *) malloc(sizeof(uint32_t) * 4);
          port_lane_list_attribute.value.u32list.count = 4;
          port_api->get_port_attribute(port_list_object_attribute.value.objlist.list[i], 1, &port_lane_list_attribute);

          std::set<int> port_lanes;
          uint32_t laneCnt = port_lane_list_attribute.value.u32list.count;
          for (int j=0 ; j<laneCnt; j++){
              port_lanes.insert(port_lane_list_attribute.value.u32list.list[j]);
          }

          if (port_lanes == lane_set){
              port_id = (sai_thrift_object_id_t) port_list_object_attribute.value.objlist.list[i];
              free(port_list_object_attribute.value.objlist.list);
              free(port_lane_list_attribute.value.u32list.list);
              return port_id;
          }
          free(port_lane_list_attribute.value.u32list.list);
      }
      printf("Didn't find port\n");
      free(port_list_object_attribute.value.objlist.list);
      return SAI_NULL_OBJECT_ID;
  }


  void sai_thrift_create_bridge_port(sai_thrift_result_t &ret, const std::vector<sai_thrift_attribute_t> & thrift_attr_list)
  {
      sai_bridge_api_t *bridge_api;
      sai_attribute_t *sai_attrs = nullptr;

      SAI_THRIFT_FUNC_LOG();

      ret.status = sai_api_query(SAI_API_BRIDGE, (void **) &bridge_api);
      if (ret.status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain bridge_api, status:%d", ret.status);
          return;
      }

      sai_uint32_t attr_size = thrift_attr_list.size();

      sai_thrift_alloc_attr(sai_attrs, attr_size);

      sai_thrift_parse_bridge_port_attributes(thrift_attr_list, sai_attrs);

      ret.status = bridge_api->create_bridge_port((sai_object_id_t *) &ret.data.oid, gSwitchId, attr_size, sai_attrs);
      if (ret.status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to create bridge port, status:%d", ret.status);
      }

      sai_thrift_free_attr(sai_attrs);
  }

  sai_thrift_status_t sai_thrift_remove_bridge_port(const sai_thrift_object_id_t bridge_port_id)
  {
      sai_bridge_api_t *bridge_api;
      sai_status_t status;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_BRIDGE, (void **) &bridge_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain bridge_api, status:%d", status);
          return status;
      }

      return bridge_api->remove_bridge_port((sai_object_id_t) bridge_port_id);
  }

  void sai_thrift_get_bridge_port_list(sai_thrift_result_t &ret, sai_thrift_object_id_t bridge_id)
  {
      std::vector<sai_thrift_object_id_t>& port_list = ret.data.objlist.object_id_list;
      sai_bridge_api_t *bridge_api;
      uint32_t max_ports = 128;
      sai_attribute_t attr;

      SAI_THRIFT_FUNC_LOG();

      ret.status = sai_api_query(SAI_API_BRIDGE, (void **) &bridge_api);
      if (ret.status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain bridge_api, status:%d", ret.status);
          return;
      }

      attr.id = SAI_BRIDGE_ATTR_PORT_LIST;
      attr.value.objlist.list = (sai_object_id_t *) calloc(max_ports, sizeof(sai_object_id_t));
      attr.value.objlist.count = max_ports;

      ret.status = bridge_api->get_bridge_attribute(bridge_id, 1, &attr);
      if (ret.status != SAI_STATUS_SUCCESS && attr.value.objlist.count > max_ports) {
          /* retry one more time with a bigger list */
          max_ports = attr.value.objlist.count;
          attr.value.objlist.list = (sai_object_id_t *) realloc(attr.value.objlist.list, max_ports * sizeof(sai_object_id_t));

          ret.status = bridge_api->get_bridge_attribute(bridge_id, 1, &attr);
      }

      if (ret.status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("Failed to obtain bridge ports list, status:%d", ret.status);
          free(attr.value.objlist.list);
          return;
      }

      for (int index = 0; index < attr.value.objlist.count; index++) {
          port_list.push_back((sai_thrift_object_id_t) attr.value.objlist.list[index]);
      }
      free(attr.value.objlist.list);
  }

  sai_thrift_status_t sai_thrift_set_bridge_port_attribute(const sai_thrift_object_id_t bridge_port_id,
                                                           const sai_thrift_attribute_t& thrift_attr)
  {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_bridge_api_t *bridge_api;
      sai_attribute_t attr;
      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_BRIDGE, (void **) &bridge_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain bridge_api, status:%d", status);
          return status;
      }

      sai_thrift_parse_bridge_port_attributes(thrift_attr_list, &attr);

      return bridge_api->set_bridge_port_attribute(bridge_port_id, &attr);
  }

  void sai_thrift_get_bridge_port_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t bridge_port_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_bridge_api_t *bridge_api;
      uint32_t attr_count = 0;
      sai_attribute_t attr[3];
	  sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_BRIDGE, (void **) &bridge_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain bridge_api, status:%d", status);
          return;
      }

      attr[0].id = SAI_BRIDGE_PORT_ATTR_TYPE;
      attr[1].id = SAI_BRIDGE_PORT_ATTR_BRIDGE_ID;
      attr_count = 2;

      status = bridge_api->get_bridge_port_attribute(bridge_port_id, attr_count, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain bridge port type, status:%d", status);
          return;
      }

	  thrift_attr.id = attr[0].id;
	  thrift_attr.value.s32 = attr[0].value.s32;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[1].id;
	  thrift_attr.value.oid = attr[1].value.oid;
	  thrift_attr_list.attr_list.push_back(thrift_attr);

      switch (attr[0].value.s32) {
      case SAI_BRIDGE_PORT_TYPE_PORT:
          attr[0].id = SAI_BRIDGE_PORT_ATTR_PORT_ID;
          attr_count = 1;
          break;

      case SAI_BRIDGE_PORT_TYPE_TUNNEL:
          attr[0].id = SAI_BRIDGE_PORT_ATTR_TUNNEL_ID;
          attr_count = 1;
          break;

      case SAI_BRIDGE_PORT_TYPE_SUB_PORT:
          attr[0].id = SAI_BRIDGE_PORT_ATTR_PORT_ID;
		  attr[1].id = SAI_BRIDGE_PORT_ATTR_VLAN_ID;
          attr_count = 2;
          break;

      default:
          return;
      }

      status = bridge_api->get_bridge_port_attribute(bridge_port_id, attr_count, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain bridge port attributes, status:%d", status);
          return;
      }

	  thrift_attr.id = attr[0].id;
	  thrift_attr.value.oid = attr[0].value.oid;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[1].id;
	  thrift_attr.value.u16 = attr[1].value.u16;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
  }

  void sai_thrift_create_bridge(sai_thrift_result_t &ret, const std::vector<sai_thrift_attribute_t> & thrift_attr_list)
  {
      sai_bridge_api_t *bridge_api;
      sai_attribute_t  *sai_attrs = nullptr;

      SAI_THRIFT_FUNC_LOG();

      ret.status = sai_api_query(SAI_API_BRIDGE, (void **) &bridge_api);
      if (ret.status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain bridge_api, status:%d", ret.status);
          return;
      }

      sai_uint32_t attr_size = thrift_attr_list.size();

      sai_thrift_alloc_attr(sai_attrs, attr_size);

      sai_thrift_parse_bridge_attributes(thrift_attr_list, sai_attrs);

      ret.status = bridge_api->create_bridge((sai_object_id_t *) &ret.data.oid, gSwitchId, attr_size, sai_attrs);
      if (ret.status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to create bridge, status:%d", ret.status);
      }

      sai_thrift_free_attr(sai_attrs);
  }

  sai_thrift_status_t sai_thrift_remove_bridge(const sai_thrift_object_id_t bridge_port_id)
  {
      sai_bridge_api_t *bridge_api;
      sai_status_t status;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_BRIDGE, (void **) &bridge_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain bridge_api, status:%d", status);
          return status;
      }

      return bridge_api->remove_bridge((sai_object_id_t) bridge_port_id);
  }

  sai_thrift_status_t sai_thrift_set_bridge_attribute(const sai_thrift_object_id_t bridge_id,
                                                           const sai_thrift_attribute_t& thrift_attr)
  {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_bridge_api_t *bridge_api;
      sai_attribute_t attr;
      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_BRIDGE, (void **) &bridge_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain bridge_api, status:%d", status);
          return status;
      }

      sai_thrift_parse_bridge_attributes(thrift_attr_list, &attr);

      return bridge_api->set_bridge_attribute(bridge_id, &attr);
  }

  void sai_thrift_get_bridge_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t bridge_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_bridge_api_t *bridge_api;
      uint32_t attr_count = 0;
      sai_attribute_t attr[4];
	  sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_BRIDGE, (void **) &bridge_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain bridge_api, status:%d", status);
          return;
      }

      attr[0].id = SAI_BRIDGE_ATTR_TYPE;
      attr[1].id = SAI_BRIDGE_ATTR_MAX_LEARNED_ADDRESSES;
	  attr[2].id = SAI_BRIDGE_ATTR_LEARN_DISABLE;
      attr_count = 3;

      status = bridge_api->get_bridge_attribute(bridge_id, attr_count, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain bridge port type, status:%d", status);
          return;
      }

	  thrift_attr.id = attr[0].id;
	  thrift_attr.value.s32 = attr[0].value.s32;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[1].id;
	  thrift_attr.value.u32 = attr[1].value.u32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[2].id;
	  thrift_attr.value.booldata = attr[2].value.booldata;
	  thrift_attr_list.attr_list.push_back(thrift_attr);

      attr[0].id = SAI_BRIDGE_ATTR_UNKNOWN_UNICAST_FLOOD_CONTROL_TYPE;
      attr[1].id = SAI_BRIDGE_ATTR_UNKNOWN_MULTICAST_FLOOD_CONTROL_TYPE;
	  attr[2].id = SAI_BRIDGE_ATTR_BROADCAST_FLOOD_CONTROL_TYPE;
      attr_count = 3;

      status = bridge_api->get_bridge_attribute(bridge_id, attr_count, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain bridge attributes, status:%d", status);
          return;
      }

	  thrift_attr.id = attr[0].id;
	  thrift_attr.value.s32 = attr[0].value.s32;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[1].id;
	  thrift_attr.value.s32 = attr[1].value.s32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[2].id;
	  thrift_attr.value.s32 = attr[2].value.s32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
  }

  sai_thrift_object_id_t sai_thrift_create_hostif(const std::vector<sai_thrift_attribute_t> &thrift_attr_list) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_hostif_api_t *hostif_api = nullptr;
      auto status = sai_api_query(SAI_API_HOSTIF, reinterpret_cast<void**>(&hostif_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return SAI_NULL_OBJECT_ID; }

      sai_attribute_t *attr_list = nullptr;
      sai_size_t attr_size = thrift_attr_list.size();
      sai_thrift_alloc_attr(attr_list, attr_size);
      sai_thrift_parse_hostif_attributes(attr_list, thrift_attr_list);

      sai_object_id_t hif_oid = 0;
      status = hostif_api->create_hostif(&hif_oid, gSwitchId, attr_size, attr_list);
      sai_thrift_free_attr(attr_list);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return hif_oid; }

      SAI_THRIFT_LOG_ERR("Failed to create OID.");

      return SAI_NULL_OBJECT_ID;
  }

  sai_thrift_status_t sai_thrift_remove_hostif(const sai_thrift_object_id_t thrift_hif_id) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_hostif_api_t *hostif_api = nullptr;
      auto status = sai_api_query(SAI_API_HOSTIF, reinterpret_cast<void**>(&hostif_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return status; }

      status = hostif_api->remove_hostif(thrift_hif_id);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return status; }

      SAI_THRIFT_LOG_ERR("Failed to remove OID.");
  }

  void sai_thrift_get_hostif_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t thrift_hif_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_hostif_api_t *hostif_api = nullptr;
      uint32_t attr_count = 0;
      sai_attribute_t attr[4];
	  sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_HOSTIF, reinterpret_cast<void**>(&hostif_api));
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain hostif api, status:%d", status);
          return;
      }

      attr[0].id = SAI_HOSTIF_ATTR_TYPE;
      attr[1].id = SAI_HOSTIF_ATTR_OBJ_ID;
	  attr[2].id = SAI_HOSTIF_ATTR_NAME;
	  attr[3].id = SAI_HOSTIF_ATTR_OPER_STATUS;
      attr_count = 4;

      status = hostif_api->get_hostif_attribute(thrift_hif_id, attr_count, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain hostif attribute, status:%d", status);
          return;
      }

	  thrift_attr.id = attr[0].id;
	  thrift_attr.value.s32 = attr[0].value.s32;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[1].id;
	  thrift_attr.value.oid = attr[1].value.oid;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[2].id;
	  memcpy((void*)thrift_attr.value.chardata.c_str(), (const void*)attr[2].value.chardata, SAI_HOSTIF_NAME_SIZE);
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[3].id;
	  thrift_attr.value.booldata = attr[3].value.booldata;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
  }

  sai_thrift_status_t sai_thrift_set_hostif_attribute(const sai_thrift_object_id_t thrift_hif_id, const sai_thrift_attribute_t &thrift_attr) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_hostif_api_t *hostif_api = nullptr;
      auto status = sai_api_query(SAI_API_HOSTIF, reinterpret_cast<void**>(&hostif_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return status; }

      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      sai_attribute_t *attr_list = nullptr;
      sai_size_t attr_size = thrift_attr_list.size();
      sai_thrift_alloc_attr(attr_list, attr_size);
      sai_thrift_parse_hostif_attributes(attr_list, thrift_attr_list);

      status = hostif_api->set_hostif_attribute(thrift_hif_id, attr_list);
      sai_thrift_free_attr(attr_list);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return status; }

      SAI_THRIFT_LOG_ERR("Failed to set attribute.");

      return status;
  }

  sai_thrift_object_id_t sai_thrift_create_hostif_table_entry(const std::vector<sai_thrift_attribute_t> &thrift_attr_list) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_hostif_api_t *hostif_api = nullptr;
      auto status = sai_api_query(SAI_API_HOSTIF, reinterpret_cast<void**>(&hostif_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return SAI_NULL_OBJECT_ID; }

      sai_attribute_t *attr_list = nullptr;
      sai_size_t attr_size = thrift_attr_list.size();
      sai_thrift_alloc_attr(attr_list, attr_size);
      sai_thrift_parse_hostif_table_entry_attributes(attr_list, thrift_attr_list);

      sai_object_id_t hif_tbl_entry_oid = 0;
      status = hostif_api->create_hostif_table_entry(&hif_tbl_entry_oid, gSwitchId, attr_size, attr_list);
      sai_thrift_free_attr(attr_list);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return hif_tbl_entry_oid; }

      SAI_THRIFT_LOG_ERR("Failed to create OID.");

      return SAI_NULL_OBJECT_ID;
  }

  sai_thrift_status_t sai_thrift_remove_hostif_table_entry(const sai_thrift_object_id_t hif_tbl_entry_oid) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_hostif_api_t *hostif_api = nullptr;
      auto status = sai_api_query(SAI_API_HOSTIF, reinterpret_cast<void**>(&hostif_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return status; }

      status = hostif_api->remove_hostif_table_entry(hif_tbl_entry_oid);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return status; }

      SAI_THRIFT_LOG_ERR("Failed to remove OID.");
  }

  void sai_thrift_get_hostif_table_entry_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t hif_tbl_entry_oid) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_hostif_api_t *hostif_api = nullptr;
      uint32_t attr_count = 0;
      sai_attribute_t attr[4];
	  sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_HOSTIF, reinterpret_cast<void**>(&hostif_api));
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain hostif api, status:%d", status);
          return;
      }

      attr[0].id = SAI_HOSTIF_TABLE_ENTRY_ATTR_TYPE;
      attr[1].id = SAI_HOSTIF_TABLE_ENTRY_ATTR_OBJ_ID;
	  attr[2].id = SAI_HOSTIF_TABLE_ENTRY_ATTR_TRAP_ID;
	  attr[3].id = SAI_HOSTIF_TABLE_ENTRY_ATTR_CHANNEL_TYPE;
      attr_count = 4;

      status = hostif_api->get_hostif_table_entry_attribute(hif_tbl_entry_oid, attr_count, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain hostif attribute, status:%d", status);
          return;
      }

	  thrift_attr.id = attr[0].id;
	  thrift_attr.value.s32 = attr[0].value.s32;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[1].id;
	  thrift_attr.value.oid = attr[1].value.oid;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[2].id;
	  thrift_attr.value.oid = attr[2].value.oid;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[3].id;
	  thrift_attr.value.s32 = attr[3].value.s32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
  }

  sai_thrift_status_t sai_thrift_set_hostif_table_entry_attribute(const sai_thrift_object_id_t hif_tbl_entry_oid, const sai_thrift_attribute_t &thrift_attr) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_hostif_api_t *hostif_api = nullptr;
      auto status = sai_api_query(SAI_API_HOSTIF, reinterpret_cast<void**>(&hostif_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return status; }

      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      sai_attribute_t *attr_list = nullptr;
      sai_size_t attr_size = thrift_attr_list.size();
      sai_thrift_alloc_attr(attr_list, attr_size);
      sai_thrift_parse_hostif_table_entry_attributes(attr_list, thrift_attr_list);

      status = hostif_api->set_hostif_table_entry_attribute(hif_tbl_entry_oid, attr_list);
      sai_thrift_free_attr(attr_list);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return status; }

      SAI_THRIFT_LOG_ERR("Failed to set attribute.");

      return status;
  }

  sai_thrift_object_id_t sai_thrift_create_hostif_trap_group(const std::vector<sai_thrift_attribute_t> &thrift_attr_list) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_hostif_api_t *hostif_api = nullptr;
      auto status = sai_api_query(SAI_API_HOSTIF, reinterpret_cast<void**>(&hostif_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return SAI_NULL_OBJECT_ID; }

      sai_attribute_t *attr_list = nullptr;
      sai_size_t attr_size = thrift_attr_list.size();
      sai_thrift_alloc_attr(attr_list, attr_size);
      sai_thrift_parse_hostif_trap_group_attributes(attr_list, thrift_attr_list);

      sai_object_id_t hostif_trap_group_oid = 0;
      status = hostif_api->create_hostif_trap_group(&hostif_trap_group_oid, gSwitchId, attr_size, attr_list);
      sai_thrift_free_attr(attr_list);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return hostif_trap_group_oid; }

      SAI_THRIFT_LOG_ERR("Failed to create OID.");

      return SAI_NULL_OBJECT_ID;
  }

  sai_thrift_status_t sai_thrift_remove_hostif_trap_group(const sai_thrift_object_id_t thrift_hostif_trap_group_id) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_hostif_api_t *hostif_api = nullptr;
      auto status = sai_api_query(SAI_API_HOSTIF, reinterpret_cast<void**>(&hostif_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return status; }

      status = hostif_api->remove_hostif_trap_group(thrift_hostif_trap_group_id);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return status; }

      SAI_THRIFT_LOG_ERR("Failed to remove OID.");

      return status;
  }

  void sai_thrift_get_hostif_trap_group_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t thrift_hostif_trap_group_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_hostif_api_t *hostif_api = nullptr;
      uint32_t attr_count = 0;
      sai_attribute_t attr[3];
	  sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_HOSTIF, reinterpret_cast<void**>(&hostif_api));
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain trap group api, status:%d", status);
          return;
      }

      attr[0].id = SAI_HOSTIF_TRAP_GROUP_ATTR_ADMIN_STATE;
      attr[1].id = SAI_HOSTIF_TRAP_GROUP_ATTR_QUEUE;
	  attr[2].id = SAI_HOSTIF_TRAP_GROUP_ATTR_POLICER;
      attr_count = 3;

      status = hostif_api->get_hostif_trap_group_attribute(thrift_hostif_trap_group_id, attr_count, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain trap group attribute, status:%d", status);
          return;
      }

	  thrift_attr.id = attr[0].id;
	  thrift_attr.value.booldata = attr[0].value.booldata;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[1].id;
	  thrift_attr.value.u32 = attr[1].value.u32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[2].id;
	  thrift_attr.value.oid = attr[2].value.oid;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
  }

  sai_thrift_status_t sai_thrift_set_hostif_trap_group_attribute(const sai_thrift_object_id_t thrift_hostif_trap_group_id,
                                                                 const sai_thrift_attribute_t &thrift_attr) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_hostif_api_t *hostif_api = nullptr;
      auto status = sai_api_query(SAI_API_HOSTIF, reinterpret_cast<void**>(&hostif_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return status; }

      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      sai_attribute_t *attr_list = nullptr;
      sai_size_t attr_size = thrift_attr_list.size();
      sai_thrift_alloc_attr(attr_list, attr_size);
      sai_thrift_parse_hostif_trap_group_attributes(attr_list, thrift_attr_list);

      status = hostif_api->set_hostif_trap_group_attribute(thrift_hostif_trap_group_id, attr_list);
      sai_thrift_free_attr(attr_list);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return status; }

      SAI_THRIFT_LOG_ERR("Failed to set attribute.");

      return status;
  }

  sai_thrift_object_id_t sai_thrift_create_hostif_trap(const std::vector<sai_thrift_attribute_t> &thrift_attr_list) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_hostif_api_t *hostif_api = nullptr;
      auto status = sai_api_query(SAI_API_HOSTIF, reinterpret_cast<void**>(&hostif_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return SAI_NULL_OBJECT_ID; }

      sai_attribute_t *attr_list = nullptr;
      sai_size_t attr_size = thrift_attr_list.size();
      sai_thrift_alloc_attr(attr_list, attr_size);
      sai_thrift_parse_hostif_trap_attributes(attr_list, thrift_attr_list);

      sai_object_id_t hostif_trap_oid = 0;
      status = hostif_api->create_hostif_trap(&hostif_trap_oid, gSwitchId, attr_size, attr_list);
      sai_thrift_free_attr(attr_list);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return hostif_trap_oid; }

      SAI_THRIFT_LOG_ERR("Failed to create OID.");

      return SAI_NULL_OBJECT_ID;
  }

  sai_thrift_status_t sai_thrift_remove_hostif_trap(const sai_thrift_object_id_t thrift_hostif_trap_id) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_hostif_api_t *hostif_api = nullptr;
      auto status = sai_api_query(SAI_API_HOSTIF, reinterpret_cast<void**>(&hostif_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return status; }

      status = hostif_api->remove_hostif_trap(thrift_hostif_trap_id);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return status; }

      SAI_THRIFT_LOG_ERR("Failed to remove OID.");

      return status;
  }

  void sai_thrift_get_hostif_trap_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t thrift_hostif_trap_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_hostif_api_t *hostif_api = nullptr;
      uint32_t attr_count = 0;
      sai_attribute_t attr[4];
	  sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_HOSTIF, reinterpret_cast<void**>(&hostif_api));
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain hostif_trap_api, status:%d", status);
          return;
      }

	  attr[0].id = SAI_HOSTIF_TRAP_ATTR_TRAP_TYPE;
      attr[1].id = SAI_HOSTIF_TRAP_ATTR_PACKET_ACTION;
      attr[2].id = SAI_HOSTIF_TRAP_ATTR_TRAP_PRIORITY;
	  attr[3].id = SAI_HOSTIF_TRAP_ATTR_TRAP_GROUP;
      attr_count = 4;

      status = hostif_api->get_hostif_trap_attribute(thrift_hostif_trap_id, attr_count, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain hostif_trap type, status:%d", status);
          return;
      }

	  thrift_attr.id = attr[0].id;
	  thrift_attr.value.s32 = attr[0].value.s32;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[1].id;
	  thrift_attr.value.s32 = attr[1].value.s32;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[2].id;
	  thrift_attr.value.u32 = attr[2].value.u32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[3].id;
	  thrift_attr.value.oid = attr[3].value.oid;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
  }

  sai_thrift_status_t sai_thrift_set_hostif_trap_attribute(const sai_thrift_object_id_t thrift_hostif_trap_id, const sai_thrift_attribute_t &thrift_attr)
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_hostif_api_t *hostif_api = nullptr;
      auto status = sai_api_query(SAI_API_HOSTIF, reinterpret_cast<void**>(&hostif_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return status; }

      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      sai_attribute_t *attr_list = nullptr;
      sai_size_t attr_size = thrift_attr_list.size();
      sai_thrift_alloc_attr(attr_list, attr_size);
      sai_thrift_parse_hostif_trap_attributes(attr_list, thrift_attr_list);

      status = hostif_api->set_hostif_trap_attribute(thrift_hostif_trap_id, attr_list);
      sai_thrift_free_attr(attr_list);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return status; }

      SAI_THRIFT_LOG_ERR("Failed to set attribute.");

      return status;
  }

    void sai_thrift_parse_acl_table_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
            case SAI_ACL_TABLE_ATTR_ACL_STAGE:
                attr_list[i].value.s32 = attribute.value.s32;
                break;
            case SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST:
                {
                    int count = attribute.value.s32list.s32list.size();
                    sai_int32_t *aclbp_list = NULL;
                    std::vector<sai_int32_t>::const_iterator it = attribute.value.s32list.s32list.begin();
                    aclbp_list = (sai_int32_t *) malloc(sizeof(sai_int32_t) * count);
                    for(int j = 0; j < count; j++, it++)
                        *(aclbp_list + j) = (sai_int32_t) *it;
                    attr_list[i].value.s32list.list = aclbp_list;
                    attr_list[i].value.s32list.count = count;
                }
                break;
            case SAI_ACL_TABLE_ATTR_FIELD_SRC_IPV6:
            case SAI_ACL_TABLE_ATTR_FIELD_DST_IPV6:
            case SAI_ACL_TABLE_ATTR_FIELD_SRC_MAC:
            case SAI_ACL_TABLE_ATTR_FIELD_DST_MAC:
            case SAI_ACL_TABLE_ATTR_FIELD_SRC_IP:
            case SAI_ACL_TABLE_ATTR_FIELD_DST_IP:
            case SAI_ACL_TABLE_ATTR_FIELD_IN_PORTS:
            case SAI_ACL_TABLE_ATTR_FIELD_OUT_PORTS:
            case SAI_ACL_TABLE_ATTR_FIELD_IN_PORT:
            case SAI_ACL_TABLE_ATTR_FIELD_OUT_PORT:
            case SAI_ACL_TABLE_ATTR_FIELD_OUTER_VLAN_ID:
            case SAI_ACL_TABLE_ATTR_FIELD_OUTER_VLAN_PRI:
            case SAI_ACL_TABLE_ATTR_FIELD_OUTER_VLAN_CFI:
            case SAI_ACL_TABLE_ATTR_FIELD_INNER_VLAN_ID:
            case SAI_ACL_TABLE_ATTR_FIELD_INNER_VLAN_PRI:
            case SAI_ACL_TABLE_ATTR_FIELD_INNER_VLAN_CFI:
            case SAI_ACL_TABLE_ATTR_FIELD_L4_SRC_PORT:
            case SAI_ACL_TABLE_ATTR_FIELD_L4_DST_PORT:
            case SAI_ACL_TABLE_ATTR_FIELD_ETHER_TYPE:
            case SAI_ACL_TABLE_ATTR_FIELD_IP_PROTOCOL:
            case SAI_ACL_TABLE_ATTR_FIELD_DSCP:
            case SAI_ACL_TABLE_ATTR_FIELD_ECN:
            case SAI_ACL_TABLE_ATTR_FIELD_TTL:
            case SAI_ACL_TABLE_ATTR_FIELD_TOS:
            case SAI_ACL_TABLE_ATTR_FIELD_IP_FLAGS:
            case SAI_ACL_TABLE_ATTR_FIELD_TCP_FLAGS:
            case SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_TYPE:
            case SAI_ACL_TABLE_ATTR_FIELD_ACL_IP_FRAG:
            case SAI_ACL_TABLE_ATTR_FIELD_IPV6_FLOW_LABEL:
            case SAI_ACL_TABLE_ATTR_FIELD_TC:
                attr_list[i].value.booldata = attribute.value.booldata;
                break;
            default:
                break;
          }
      }
  }

  void sai_thrift_parse_acl_entry_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
            case SAI_ACL_ENTRY_ATTR_TABLE_ID:
                attr_list[i].value.oid = attribute.value.oid;
                break;
            case SAI_ACL_ENTRY_ATTR_PRIORITY:
                attr_list[i].value.u32 = attribute.value.u32;
                break;
            case SAI_ACL_ENTRY_ATTR_ADMIN_STATE:
                attr_list[i].value.booldata = attribute.value.booldata;
                break;
            case SAI_ACL_ENTRY_ATTR_FIELD_SRC_IPV6:
            case SAI_ACL_ENTRY_ATTR_FIELD_DST_IPV6:
				attr_list[i].value.aclfield.enable = attribute.value.aclfield.enable;
                sai_thrift_string_to_v6_ip(attribute.value.aclfield.data.ip6, attr_list[i].value.aclfield.data.ip6);
                sai_thrift_string_to_v6_ip(attribute.value.aclfield.mask.ip6, attr_list[i].value.aclfield.mask.ip6);
                break;
            case SAI_ACL_ENTRY_ATTR_FIELD_SRC_MAC:
            case SAI_ACL_ENTRY_ATTR_FIELD_DST_MAC:
				attr_list[i].value.aclfield.enable = attribute.value.aclfield.enable;
                sai_thrift_string_to_mac(attribute.value.aclfield.data.mac, attr_list[i].value.aclfield.data.mac);
                sai_thrift_string_to_mac(attribute.value.aclfield.mask.mac, attr_list[i].value.aclfield.mask.mac);
                break;
            case SAI_ACL_ENTRY_ATTR_FIELD_SRC_IP:
            case SAI_ACL_ENTRY_ATTR_FIELD_DST_IP:
				attr_list[i].value.aclfield.enable = attribute.value.aclfield.enable;
                sai_thrift_string_to_v4_ip(attribute.value.aclfield.data.ip4, &attr_list[i].value.aclfield.data.ip4);
                sai_thrift_string_to_v4_ip(attribute.value.aclfield.mask.ip4, &attr_list[i].value.aclfield.mask.ip4);
                break;
            case SAI_ACL_ENTRY_ATTR_FIELD_IN_PORT:
				attr_list[i].value.aclfield.enable = attribute.value.aclfield.enable;
                attr_list[i].value.aclfield.data.oid = attribute.value.aclfield.data.oid;
                break;
            case SAI_ACL_ENTRY_ATTR_FIELD_IN_PORTS:
                {
                    int count = attribute.value.aclfield.data.objlist.object_id_list.size();
                    sai_object_id_t *oid_list = NULL;
                    std::vector<sai_thrift_object_id_t>::const_iterator it = attribute.value.aclfield.data.objlist.object_id_list.begin();
                    oid_list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * count);
                    for(int j = 0; j < count; j++, it++)
                        *(oid_list + j) = (sai_object_id_t) *it;
					attr_list[i].value.aclfield.enable = attribute.value.aclfield.enable;
                    attr_list[i].value.aclfield.data.objlist.list =  oid_list;
                    attr_list[i].value.aclfield.data.objlist.count =  count;
                }
                break;
            case SAI_ACL_ENTRY_ATTR_FIELD_OUT_PORT:
				attr_list[i].value.aclfield.enable = attribute.value.aclfield.enable;
                attr_list[i].value.aclfield.data.oid = attribute.value.aclfield.data.oid;
                break;
            /*
            case SAI_ACL_ENTRY_ATTR_FIELD_OUT_PORTS:
            */
            case SAI_ACL_ENTRY_ATTR_FIELD_OUTER_VLAN_PRI:
            case SAI_ACL_ENTRY_ATTR_FIELD_OUTER_VLAN_CFI:
            case SAI_ACL_ENTRY_ATTR_FIELD_INNER_VLAN_PRI:
            case SAI_ACL_ENTRY_ATTR_FIELD_INNER_VLAN_CFI:
				attr_list[i].value.aclfield.enable = attribute.value.aclfield.enable;
				attr_list[i].value.aclfield.data.u8 = attribute.value.aclfield.data.u8;
				attr_list[i].value.aclfield.mask.u8 = attribute.value.aclfield.mask.u8;
                break;
            case SAI_ACL_ENTRY_ATTR_FIELD_OUTER_VLAN_ID:
            case SAI_ACL_ENTRY_ATTR_FIELD_INNER_VLAN_ID:
            case SAI_ACL_ENTRY_ATTR_FIELD_L4_SRC_PORT:
            case SAI_ACL_ENTRY_ATTR_FIELD_L4_DST_PORT:
            case SAI_ACL_ENTRY_ATTR_FIELD_ETHER_TYPE:
				attr_list[i].value.aclfield.enable = attribute.value.aclfield.enable;
                attr_list[i].value.aclfield.data.u16 = attribute.value.aclfield.data.u16;
                attr_list[i].value.aclfield.mask.u16 = attribute.value.aclfield.mask.u16;
                break;
            case SAI_ACL_ENTRY_ATTR_FIELD_IP_PROTOCOL:
            case SAI_ACL_ENTRY_ATTR_FIELD_DSCP:
            case SAI_ACL_ENTRY_ATTR_FIELD_ECN:
            case SAI_ACL_ENTRY_ATTR_FIELD_TTL:
            case SAI_ACL_ENTRY_ATTR_FIELD_TOS:
            case SAI_ACL_ENTRY_ATTR_FIELD_IP_FLAGS:
            case SAI_ACL_ENTRY_ATTR_FIELD_TCP_FLAGS:
            case SAI_ACL_ENTRY_ATTR_FIELD_ACL_IP_TYPE:
            case SAI_ACL_ENTRY_ATTR_FIELD_ACL_IP_FRAG:
            case SAI_ACL_ENTRY_ATTR_FIELD_TC:
				attr_list[i].value.aclfield.enable = attribute.value.aclfield.enable;
                attr_list[i].value.aclfield.data.u8 = attribute.value.aclfield.data.u8;
                attr_list[i].value.aclfield.mask.u8 = attribute.value.aclfield.mask.u8;
                break;
            case SAI_ACL_ENTRY_ATTR_FIELD_IPV6_FLOW_LABEL:
				attr_list[i].value.aclfield.enable = attribute.value.aclfield.enable;
                attr_list[i].value.aclfield.data.u32 = attribute.value.aclfield.data.u32;
                attr_list[i].value.aclfield.mask.u32 = attribute.value.aclfield.mask.u32;
                break;
		    case SAI_ACL_ENTRY_ATTR_ACTION_INGRESS_SAMPLEPACKET_ENABLE:
				attr_list[i].value.aclaction.enable = attribute.value.aclaction.enable;
                attr_list[i].value.aclaction.parameter.oid = attribute.value.aclaction.parameter.oid;
                break;
            case SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_INGRESS:
            case SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_EGRESS:
                {
                    int count = attribute.value.aclaction.parameter.objlist.object_id_list.size();
                    sai_object_id_t *oid_list = NULL;
                    std::vector<sai_thrift_object_id_t>::const_iterator it = attribute.value.aclaction.parameter.objlist.object_id_list.begin();
                    oid_list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * count);
                    for(int j = 0; j < count; j++, it++)
                        *(oid_list + j) = (sai_object_id_t) *it;
					attr_list[i].value.aclaction.enable = attribute.value.aclaction.enable;
                    attr_list[i].value.aclaction.parameter.objlist.list =  oid_list;
                    attr_list[i].value.aclaction.parameter.objlist.count =  count;
                }
                break;
            case SAI_ACL_ENTRY_ATTR_ACTION_SET_POLICER:
				attr_list[i].value.aclaction.enable = attribute.value.aclaction.enable;
                attr_list[i].value.aclfield.data.oid = attribute.value.aclfield.data.oid;
                break;
            case SAI_ACL_ENTRY_ATTR_ACTION_COUNTER:
				attr_list[i].value.aclaction.enable = attribute.value.aclaction.enable;
                attr_list[i].value.aclfield.data.oid = attribute.value.aclfield.data.oid;
                break;
            case SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION:
                attr_list[i].value.aclaction.enable        = attribute.value.aclaction.enable;
                attr_list[i].value.aclaction.parameter.s32 = attribute.value.aclaction.parameter.s32;
                break;
            case SAI_ACL_ENTRY_ATTR_ACTION_SET_OUTER_VLAN_ID:
            case SAI_ACL_ENTRY_ATTR_ACTION_SET_INNER_VLAN_ID:
				attr_list[i].value.aclaction.enable        = attribute.value.aclaction.enable;
                attr_list[i].value.aclaction.parameter.u16 = attribute.value.aclaction.parameter.u16;
                break;
			case SAI_ACL_ENTRY_ATTR_ACTION_SET_OUTER_VLAN_PRI:
			case SAI_ACL_ENTRY_ATTR_ACTION_SET_INNER_VLAN_PRI:
				attr_list[i].value.aclaction.enable        = attribute.value.aclaction.enable;
                attr_list[i].value.aclaction.parameter.u8 = attribute.value.aclaction.parameter.u8;
				break;
            case SAI_ACL_ENTRY_ATTR_ACTION_SET_DO_NOT_LEARN :
				attr_list[i].value.aclaction.enable        = attribute.value.aclaction.enable;
                break;
              default:
                break;
          }
      }
  }

  void sai_thrift_parse_acl_table_group_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
            case SAI_ACL_TABLE_GROUP_ATTR_ACL_STAGE:
                attr_list[i].value.s32 = attribute.value.s32;
                break;
            case SAI_ACL_TABLE_GROUP_ATTR_ACL_BIND_POINT_TYPE_LIST:
                {
                    int count = attribute.value.s32list.s32list.size();
                    sai_int32_t *s32_list = NULL;
                    std::vector<sai_int32_t>::const_iterator it = attribute.value.s32list.s32list.begin();
                    s32_list = (sai_int32_t *) malloc(sizeof(sai_int32_t) * count);
                    for(int j = 0; j < count; j++, it++)
                        *(s32_list + j) = (sai_int32_t) *it;
                    attr_list[i].value.s32list.list = s32_list;
                    attr_list[i].value.s32list.count = count;
                }
                break;
            case SAI_ACL_TABLE_GROUP_ATTR_TYPE:
                attr_list[i].value.s32 = attribute.value.s32;
                break;
            default:
                break;
          }
      }
  }

  void sai_thrift_parse_acl_table_group_member_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
            case SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_GROUP_ID:
                attr_list[i].value.oid = attribute.value.oid;
                break;
            case SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_ID:
                attr_list[i].value.oid = attribute.value.oid;
                break;
            case SAI_ACL_TABLE_GROUP_MEMBER_ATTR_PRIORITY:
                attr_list[i].value.u32 = attribute.value.u32;
                break;
            default:
                break;
          }
      }
  }

  void sai_thrift_convert_to_acl_counter_attributes(
          const std::vector<sai_thrift_attribute_t> &thrift_attr_list,
          sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
              case SAI_ACL_COUNTER_ATTR_TABLE_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;
              case SAI_ACL_COUNTER_ATTR_ENABLE_PACKET_COUNT:
                  attr_list[i].value.booldata = attribute.value.booldata;
                  break;
              case SAI_ACL_COUNTER_ATTR_ENABLE_BYTE_COUNT:
                  attr_list[i].value.booldata = attribute.value.booldata;
                  break;
              case SAI_ACL_COUNTER_ATTR_PACKETS:
                  attr_list[i].value.u64= attribute.value.u64;
                  break;
              case SAI_ACL_COUNTER_ATTR_BYTES:
                  attr_list[i].value.u64= attribute.value.u64;
                  break;
          }
      }
  }

  void sai_thrift_convert_to_acl_thrift_counter_attributes(
          sai_attribute_t *attr_list,
          uint32_t attr_count,
          std::vector<sai_thrift_attribute_value_t> &thrift_attr_value_list) {
      sai_attribute_t attribute;
      sai_thrift_attribute_value_t thrift_attribute_value;
      for(uint32_t i = 0; i < attr_count; i++) {
          attribute = attr_list[i];
          switch (attribute.id) {
              case SAI_ACL_COUNTER_ATTR_TABLE_ID:
                  thrift_attribute_value.oid = attribute.value.oid;
                  break;
              case SAI_ACL_COUNTER_ATTR_ENABLE_PACKET_COUNT:
                  thrift_attribute_value.booldata = attribute.value.booldata;
                  break;
              case SAI_ACL_COUNTER_ATTR_ENABLE_BYTE_COUNT:
                  thrift_attribute_value.booldata = attribute.value.booldata;
                  break;
              case SAI_ACL_COUNTER_ATTR_PACKETS:
                  thrift_attribute_value.u64= attribute.value.u64;
                  break;
              case SAI_ACL_COUNTER_ATTR_BYTES:
                  thrift_attribute_value.u64= attribute.value.u64;
                  break;
          }
          thrift_attr_value_list.push_back(thrift_attribute_value);
      }
  }

  sai_thrift_object_id_t sai_thrift_create_acl_table(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      sai_object_id_t acl_table = 0ULL;
      sai_acl_api_t *acl_api;
      sai_status_t status = SAI_STATUS_SUCCESS;
	  printf("sai_thrift_create_acl_table\n");
      status = sai_api_query(SAI_API_ACL, (void **) &acl_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }

      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parse_acl_table_attributes(thrift_attr_list, attr_list);
      uint32_t attr_count = thrift_attr_list.size();
      status = acl_api->create_acl_table(&acl_table, gSwitchId, attr_count, attr_list);
      if (status != SAI_STATUS_SUCCESS)
      {
          printf("create acl table fail !\n");
      }
      free(attr_list);
      return acl_table;
  }

  sai_thrift_status_t sai_thrift_remove_acl_table(const sai_thrift_object_id_t acl_table_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_acl_api_t *acl_api;
	  printf("sai_thrift_remove_acl_table\n");
      status = sai_api_query(SAI_API_ACL, (void **) &acl_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      status = acl_api->remove_acl_table(acl_table_id);
      if (status != SAI_STATUS_SUCCESS)
      {
          printf("remove acl table fail !\n");
      }
      return status;
  }

  void sai_thrift_get_acl_table_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t acl_table_id, const std::vector < int32_t > & thrift_attr_ids)
  {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_acl_api_t *acl_api;
      uint32_t attr_count = 0;
      uint32_t index = 0;
	  uint32_t ii = 0;
      sai_attribute_t *attr_list;
      sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_ACL, (void **) &acl_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain acl_api, status:%d", status);
          return;
      }

      attr_count = thrift_attr_ids.size();
      attr_list = (sai_attribute_t*)malloc(sizeof(sai_attribute_t) * thrift_attr_ids.size());

	  std::vector<int32_t>::const_iterator it = thrift_attr_ids.begin();

      for (index = 0; index < thrift_attr_ids.size(); index++, it++)
      {
          attr_list[index].id = (int32_t)*it;

          if (SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST == attr_list[index].id)
          {
              attr_list[index].value.s32list.count = 5;
              attr_list[index].value.s32list.list = (int32_t*)malloc(sizeof(int32_t) * 5);
          }

          if (SAI_ACL_TABLE_ATTR_ENTRY_LIST == attr_list[index].id)
          {
              attr_list[index].value.objlist.count = 100;
              attr_list[index].value.objlist.list = (sai_object_id_t*)malloc(sizeof(sai_object_id_t) * 100);
          }
      }

      status = acl_api->get_acl_table_attribute(acl_table_id, attr_count, attr_list);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("failed to obtain acl table group type, status:%d", status);
          return;
      }

      for (index = 0; index < attr_count; index++)
      {
          thrift_attr.id = attr_list[index].id;
          switch (attr_list[index].id)
          {
              case SAI_ACL_TABLE_ATTR_ACL_STAGE:
                  thrift_attr.value.s32 = attr_list[index].value.s32;
                  break;
              case SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST:
                  {
                      thrift_attr.value.s32list.count = attr_list[index].value.s32list.count;
                      std :: vector < sai_int32_t > & bind_point_list = thrift_attr.value.s32list.s32list;
                      for (ii = 0; ii < attr_list[index].value.s32list.count; ii++)
                      {
                          bind_point_list.push_back((sai_int32_t) attr_list[index].value.s32list.list[ii]);
                      }
                  }
                  break;
              case SAI_ACL_TABLE_ATTR_SIZE:
                  thrift_attr.value.u32 = attr_list[index].value.u32;
				  break;
              case SAI_ACL_TABLE_ATTR_ENTRY_LIST:
                  {
                      thrift_attr.value.objlist.count = attr_list[index].value.objlist.count;
                      std :: vector < sai_thrift_object_id_t > & entry_list = thrift_attr.value.objlist.object_id_list;
                      for (ii = 0; ii < attr_list[index].value.objlist.count; ii++)
                      {
                          entry_list.push_back((sai_thrift_object_id_t) attr_list[index].value.objlist.list[ii]);
                      }
                  }
                  break;
              case SAI_ACL_TABLE_ATTR_AVAILABLE_ACL_ENTRY:
                  thrift_attr.value.u32 = attr_list[index].value.u32;
                  break;
              case SAI_ACL_TABLE_ATTR_AVAILABLE_ACL_COUNTER:
                  thrift_attr.value.u32 = attr_list[index].value.u32;
                  break;
			  default:/* All Not support feature has returned by the function get_acl_table_attribute */
			  	  thrift_attr.value.booldata = attr_list[index].value.booldata;
          }
		  thrift_attr_list.attr_list.push_back(thrift_attr);

		  /* free memory after push back */
          if ((SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST == attr_list[index].id) && (attr_list[index].value.s32list.list))
          {
              free(attr_list[index].value.s32list.list);
          }

          if ((SAI_ACL_TABLE_ATTR_ENTRY_LIST == attr_list[index].id) && (attr_list[index].value.objlist.list))
          {
              free(attr_list[index].value.objlist.list);
          }
      }

      if (attr_list)
      {
          free(attr_list);
      }

	  return;

  }

  sai_thrift_object_id_t sai_thrift_create_acl_entry(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      sai_object_id_t acl_entry = 0ULL;
      sai_acl_api_t *acl_api;
      sai_status_t status = SAI_STATUS_SUCCESS;
	  printf("sai_thrift_create_acl_entry\n");
      status = sai_api_query(SAI_API_ACL, (void **) &acl_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }

      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parse_acl_entry_attributes(thrift_attr_list, attr_list);
      uint32_t attr_count = thrift_attr_list.size();
      status = acl_api->create_acl_entry(&acl_entry, gSwitchId, attr_count, attr_list);
	  if (status != SAI_STATUS_SUCCESS)
      {
          printf("create acl entry fail !\n");
      }
      free(attr_list);
      return acl_entry;
  }

  sai_thrift_status_t sai_thrift_remove_acl_entry(const sai_thrift_object_id_t acl_entry) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_acl_api_t *acl_api;
	  printf("sai_thrift_remove_acl_entry\n");
      status = sai_api_query(SAI_API_ACL, (void **) &acl_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      status = acl_api->remove_acl_entry(acl_entry);
	  if (status != SAI_STATUS_SUCCESS)
      {
          printf("remove acl entry fail !\n");
      }
      return status;
  }

  sai_thrift_status_t sai_thrift_set_acl_entry_attribute(const sai_thrift_object_id_t acl_entry_id, const sai_thrift_attribute_t& thrift_attr)
  {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_acl_api_t *acl_api;
      sai_attribute_t attr;
      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_ACL, (void **) &acl_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain acl_api, status:%d", status);
          return status;
      }

      sai_thrift_parse_acl_entry_attributes(thrift_attr_list, &attr);

      return acl_api->set_acl_entry_attribute(acl_entry_id, &attr);
  }

  void sai_thrift_get_acl_entry_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t acl_entry_id, const std :: vector < int32_t > & thrift_attr_ids)
  {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_acl_api_t *acl_api;
      uint32_t attr_count = 0;
      uint32_t index = 0;
      uint32_t ii = 0;
      sai_attribute_t *attr_list;
      sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_ACL, (void **) &acl_api);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("failed to obtain acl_api, status:%d", status);
          return;
      }

      attr_count = thrift_attr_ids.size();
      attr_list = (sai_attribute_t*)malloc(sizeof(sai_attribute_t) * thrift_attr_ids.size());

      std::vector<int32_t>::const_iterator it = thrift_attr_ids.begin();

      for (index = 0; index < thrift_attr_ids.size(); index++, it++)
      {
          attr_list[index].id = (int32_t)*it;
      }

      status = acl_api->get_acl_entry_attribute(acl_entry_id, attr_count, attr_list);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("failed to obtain acl entry attribute, status:%d", status);
          return;
      }

      for (index = 0; index < attr_count; index++)
      {
          thrift_attr.id = attr_list[index].id;
          switch (attr_list[index].id)
          {
              case SAI_ACL_ENTRY_ATTR_TABLE_ID:
                  thrift_attr.value.oid = attr_list[index].value.oid;
                  break;
              case SAI_ACL_ENTRY_ATTR_PRIORITY:
                  thrift_attr.value.u32 = attr_list[index].value.u32;
                  break;
              case SAI_ACL_ENTRY_ATTR_ADMIN_STATE:
                  thrift_attr.value.booldata = attr_list[index].value.booldata;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_SRC_IPV6:
				  thrift_attr.value.aclfield.data.ip6 = sai_thrift_v6_ip_to_string(attr_list[index].value.aclfield.data.ip6);
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_DST_IPV6:
                  thrift_attr.value.aclfield.data.ip6 = sai_thrift_v6_ip_to_string(attr_list[index].value.aclfield.data.ip6);
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_SRC_MAC:
				  thrift_attr.value.aclfield.data.mac = sai_thrift_mac_to_string(attr_list[index].value.aclfield.data.mac);
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_DST_MAC:
                  thrift_attr.value.aclfield.data.mac = sai_thrift_mac_to_string(attr_list[index].value.aclfield.data.mac);
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_SRC_IP:
				  thrift_attr.value.aclfield.data.ip4 = sai_thrift_v4_ip_to_string(attr_list[index].value.aclfield.data.ip4);
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_DST_IP:
                  thrift_attr.value.aclfield.data.ip4 = sai_thrift_v4_ip_to_string(attr_list[index].value.aclfield.data.ip4);
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_IN_PORTS:
              case SAI_ACL_ENTRY_ATTR_FIELD_OUT_PORTS:
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_IN_PORT:
                  thrift_attr.value.aclfield.data.oid = attr_list[index].value.aclfield.data.oid;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_OUT_PORT:
                  thrift_attr.value.aclfield.data.oid = attr_list[index].value.aclfield.data.oid;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_SRC_PORT:
                  thrift_attr.value.aclfield.data.oid = attr_list[index].value.aclfield.data.oid;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_OUTER_VLAN_ID:
                  thrift_attr.value.aclfield.data.u16 = attr_list[index].value.aclfield.data.u16;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_OUTER_VLAN_PRI:
                  thrift_attr.value.aclfield.data.u8 = attr_list[index].value.aclfield.data.u8;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_OUTER_VLAN_CFI:
                  thrift_attr.value.aclfield.data.u8 = attr_list[index].value.aclfield.data.u8;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_INNER_VLAN_ID:
                  thrift_attr.value.aclfield.data.u16 = attr_list[index].value.aclfield.data.u16;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_INNER_VLAN_PRI:
                  thrift_attr.value.aclfield.data.u8 = attr_list[index].value.aclfield.data.u8;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_INNER_VLAN_CFI:
                  thrift_attr.value.aclfield.data.u8 = attr_list[index].value.aclfield.data.u8;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_L4_SRC_PORT:
                  thrift_attr.value.aclfield.data.u16 = attr_list[index].value.aclfield.data.u16;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_L4_DST_PORT:
                  thrift_attr.value.aclfield.data.u16 = attr_list[index].value.aclfield.data.u16;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_ETHER_TYPE:
                  thrift_attr.value.aclfield.data.u16 = attr_list[index].value.aclfield.data.u16;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_IP_PROTOCOL:
                  thrift_attr.value.aclfield.data.u8 = attr_list[index].value.aclfield.data.u8;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_DSCP:
                  thrift_attr.value.aclfield.data.u8 = attr_list[index].value.aclfield.data.u8;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_ECN:
                  thrift_attr.value.aclfield.data.u8 = attr_list[index].value.aclfield.data.u8;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_TTL:
                  thrift_attr.value.aclfield.data.u8 = attr_list[index].value.aclfield.data.u8;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_TOS:
                  thrift_attr.value.aclfield.data.u8 = attr_list[index].value.aclfield.data.u8;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_IP_FLAGS:
                  thrift_attr.value.aclfield.data.u8 = attr_list[index].value.aclfield.data.u8;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_TCP_FLAGS:
                  thrift_attr.value.aclfield.data.u8 = attr_list[index].value.aclfield.data.u8;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_ACL_IP_TYPE:
                  thrift_attr.value.aclfield.data.s32 = attr_list[index].value.aclfield.data.s32;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_ACL_IP_FRAG:
                  thrift_attr.value.aclfield.data.s32 = attr_list[index].value.aclfield.data.s32;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_IPV6_FLOW_LABEL:
                  thrift_attr.value.aclfield.data.u32 = attr_list[index].value.aclfield.data.u32;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_TC:
                  thrift_attr.value.aclfield.data.u8 = attr_list[index].value.aclfield.data.u8;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_ICMP_TYPE:
                  thrift_attr.value.aclfield.data.u8 = attr_list[index].value.aclfield.data.u8;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_ICMP_CODE:
                  thrift_attr.value.aclfield.data.u8 = attr_list[index].value.aclfield.data.u8;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_PACKET_VLAN:
                  thrift_attr.value.aclfield.data.s32 = attr_list[index].value.aclfield.data.s32;
                  break;
			  /*
              case SAI_ACL_ENTRY_ATTR_FIELD_TUNNEL_VNI:
                  thrift_attr.value.aclfield.data.u32 = attr_list[index].value.aclfield.data.u32;
                  break;
              */
              case SAI_ACL_ENTRY_ATTR_FIELD_FDB_DST_USER_META:
              case SAI_ACL_ENTRY_ATTR_FIELD_ROUTE_DST_USER_META:
              case SAI_ACL_ENTRY_ATTR_FIELD_NEIGHBOR_DST_USER_META:
              case SAI_ACL_ENTRY_ATTR_FIELD_PORT_USER_META:
              case SAI_ACL_ENTRY_ATTR_FIELD_VLAN_USER_META:
              case SAI_ACL_ENTRY_ATTR_FIELD_ACL_USER_META:
                  thrift_attr.value.aclfield.data.u32 = attr_list[index].value.aclfield.data.u32;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_FDB_NPU_META_DST_HIT:
              case SAI_ACL_ENTRY_ATTR_FIELD_NEIGHBOR_NPU_META_DST_HIT:
              case SAI_ACL_ENTRY_ATTR_FIELD_ROUTE_NPU_META_DST_HIT:
                  thrift_attr.value.aclfield.data.u8 = attr_list[index].value.aclfield.data.booldata;
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_ACL_RANGE_TYPE :    /* need revise */
                  break;
              case SAI_ACL_ENTRY_ATTR_FIELD_IPV6_NEXT_HEADER:
                  thrift_attr.value.aclfield.data.u8 = attr_list[index].value.aclfield.data.u8;
                  break;
                  /* key end */
              case SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT:
                  thrift_attr.value.aclaction.parameter.oid = attr_list[index].value.aclaction.parameter.oid;
                  break;
              case SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION:
                  thrift_attr.value.aclaction.parameter.s32 = attr_list[index].value.aclaction.parameter.s32;
                  break;
              case SAI_ACL_ENTRY_ATTR_ACTION_FLOOD :    /* need revise */
                  break;
              case SAI_ACL_ENTRY_ATTR_ACTION_COUNTER:
                  thrift_attr.value.aclaction.parameter.oid = attr_list[index].value.aclaction.parameter.oid;
                  break;
              case SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_INGRESS:
              case SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_EGRESS :    /* need revise */
                  break;
              case SAI_ACL_ENTRY_ATTR_ACTION_SET_POLICER:
                  thrift_attr.value.aclaction.parameter.oid = attr_list[index].value.aclaction.parameter.oid;
                  break;
              case SAI_ACL_ENTRY_ATTR_ACTION_DECREMENT_TTL :    /* need revise */
                  break;
              case SAI_ACL_ENTRY_ATTR_ACTION_SET_TC:
                  thrift_attr.value.aclaction.parameter.u8 = attr_list[index].value.aclaction.parameter.u8;
                  break;
              case SAI_ACL_ENTRY_ATTR_ACTION_SET_PACKET_COLOR:
                  thrift_attr.value.aclaction.parameter.s32 = attr_list[index].value.aclaction.parameter.s32;
                  break;
              case SAI_ACL_ENTRY_ATTR_ACTION_SET_INNER_VLAN_ID:
                  thrift_attr.value.aclaction.parameter.u16 = attr_list[index].value.aclaction.parameter.u16;
                  break;
              case SAI_ACL_ENTRY_ATTR_ACTION_SET_INNER_VLAN_PRI:
                  thrift_attr.value.aclaction.parameter.u8 = attr_list[index].value.aclaction.parameter.u8;
                  break;
              case SAI_ACL_ENTRY_ATTR_ACTION_SET_OUTER_VLAN_ID:
                  thrift_attr.value.aclaction.parameter.u16 = attr_list[index].value.aclaction.parameter.u16;
                  break;
              case SAI_ACL_ENTRY_ATTR_ACTION_SET_OUTER_VLAN_PRI:
                  thrift_attr.value.aclaction.parameter.u8 = attr_list[index].value.aclaction.parameter.u8;
                  break;
              case SAI_ACL_ENTRY_ATTR_ACTION_SET_DSCP:
                  thrift_attr.value.aclaction.parameter.u8 = attr_list[index].value.aclaction.parameter.u8;
                  break;
              case SAI_ACL_ENTRY_ATTR_ACTION_SET_ECN:
                  thrift_attr.value.aclaction.parameter.u8 = attr_list[index].value.aclaction.parameter.u8;
                  break;
              case SAI_ACL_ENTRY_ATTR_ACTION_INGRESS_SAMPLEPACKET_ENABLE:
              case SAI_ACL_ENTRY_ATTR_ACTION_EGRESS_SAMPLEPACKET_ENABLE:
                  thrift_attr.value.aclaction.parameter.oid = attr_list[index].value.aclaction.parameter.oid;
                  break;
              case SAI_ACL_ENTRY_ATTR_ACTION_SET_ACL_META_DATA:
                  thrift_attr.value.aclaction.parameter.u32 = attr_list[index].value.aclaction.parameter.u32;
                  break;
              case SAI_ACL_ENTRY_ATTR_ACTION_EGRESS_BLOCK_PORT_LIST :    /* need revise */
                  break;
              case SAI_ACL_ENTRY_ATTR_ACTION_SET_USER_TRAP_ID:
                  thrift_attr.value.aclaction.parameter.oid = attr_list[index].value.aclaction.parameter.oid;
                  break;
              case SAI_ACL_ENTRY_ATTR_ACTION_SET_DO_NOT_LEARN :    /* need revise */
                  break;
          }

          thrift_attr_list.attr_list.push_back(thrift_attr);
      }

	  if (attr_list)
      {
          free(attr_list);
      }

	  return;
  }

  sai_thrift_object_id_t sai_thrift_create_acl_table_group(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      sai_object_id_t acl_table_group_id = 0ULL;
      sai_acl_api_t *acl_api;
      sai_status_t status = SAI_STATUS_SUCCESS;
	  printf("sai_thrift_create_acl_table_group\n");
      status = sai_api_query(SAI_API_ACL, (void **) &acl_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }

      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parse_acl_table_group_attributes(thrift_attr_list, attr_list);
      uint32_t attr_count = thrift_attr_list.size();
      status = acl_api->create_acl_table_group(&acl_table_group_id, gSwitchId, attr_count, attr_list);
	  if (status != SAI_STATUS_SUCCESS)
      {
          printf("create acl table group fail !\n");
      }
      free(attr_list);
      return acl_table_group_id;
  }

  sai_thrift_status_t sai_thrift_remove_acl_table_group(const sai_thrift_object_id_t acl_table_group_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_acl_api_t *acl_api;
	  printf("sai_thrift_remove_acl_table_group\n");
      status = sai_api_query(SAI_API_ACL, (void **) &acl_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      status = acl_api->remove_acl_table_group(acl_table_group_id);
	  if (status != SAI_STATUS_SUCCESS)
      {
          printf("remove acl table group fail !\n");
      }
      return status;
  }

  void sai_thrift_get_acl_table_group_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t acl_table_group_id)
  {
  	  sai_status_t status = SAI_STATUS_SUCCESS;
      sai_acl_api_t *acl_api;
      uint32_t attr_count = 0;
	  int32_t index = 0;
      sai_attribute_t attr_list[4];
	  sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_ACL, (void **) &acl_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain acl_api, status:%d", status);
          return;
      }

      attr_list[0].id = SAI_ACL_TABLE_GROUP_ATTR_ACL_STAGE;
      attr_list[1].id = SAI_ACL_TABLE_GROUP_ATTR_ACL_BIND_POINT_TYPE_LIST;
      attr_list[2].id = SAI_ACL_TABLE_GROUP_ATTR_TYPE;
      attr_list[3].id = SAI_ACL_TABLE_GROUP_ATTR_MEMBER_LIST;
      attr_count = 4;

      attr_list[1].value.s32list.list = (int32_t*)malloc(sizeof(int32_t) * 5);
      attr_list[1].value.s32list.count = 5;

      attr_list[3].value.objlist.list = (sai_object_id_t*)malloc(sizeof(sai_object_id_t) * 100);
      attr_list[3].value.objlist.count = 100;

      status = acl_api->get_acl_table_group_attribute(acl_table_group_id, attr_count, attr_list);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain acl table group type, status:%d", status);
          return;
      }

	  thrift_attr.id = attr_list[0].id;
	  thrift_attr.value.s32 = attr_list[0].value.s32;
      thrift_attr_list.attr_list.push_back(thrift_attr);

	  thrift_attr.id = attr_list[1].id;
	  thrift_attr.value.s32list.count = attr_list[1].value.s32list.count;
      std::vector < sai_int32_t > & bind_point_list = thrift_attr.value.s32list.s32list;
      for (index = 0; index < attr_list[1].value.s32list.count; index++)
      {
          bind_point_list.push_back((sai_int32_t) attr_list[1].value.s32list.list[index]);
      }
      thrift_attr_list.attr_list.push_back(thrift_attr);

	  thrift_attr.id = attr_list[2].id;
	  thrift_attr.value.s32 = attr_list[2].value.s32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);

	  thrift_attr.id = attr_list[3].id;
	  thrift_attr.value.objlist.count = attr_list[3].value.objlist.count;
	  std::vector < sai_thrift_object_id_t > & member_list = thrift_attr.value.objlist.object_id_list;
      for (index = 0; index < attr_list[3].value.objlist.count; index++)
      {
          member_list.push_back((sai_thrift_object_id_t) attr_list[3].value.objlist.list[index]);
      }
	  thrift_attr_list.attr_list.push_back(thrift_attr);

      if (attr_list[1].value.s32list.list)
      {
		  free(attr_list[1].value.s32list.list);
      }

	  if (attr_list[3].value.objlist.list)
      {
		  free(attr_list[3].value.objlist.list);
      }

	  return;
  }

  sai_thrift_object_id_t sai_thrift_create_acl_table_group_member(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      sai_object_id_t acl_table_group_member_id = 0ULL;
      sai_acl_api_t *acl_api;
      sai_status_t status = SAI_STATUS_SUCCESS;
	  printf("sai_thrift_create_acl_table_group_member\n");
      status = sai_api_query(SAI_API_ACL, (void **) &acl_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }

      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parse_acl_table_group_member_attributes(thrift_attr_list, attr_list);
      uint32_t attr_count = thrift_attr_list.size();
      status = acl_api->create_acl_table_group_member(&acl_table_group_member_id, gSwitchId, attr_count, attr_list);
	  if (status != SAI_STATUS_SUCCESS)
      {
          printf("create acl table group member fail !\n");
      }
      free(attr_list);
      return acl_table_group_member_id;
  }

  sai_thrift_status_t sai_thrift_remove_acl_table_group_member(const sai_thrift_object_id_t acl_table_group_member_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_acl_api_t *acl_api;
	  printf("sai_thrift_remove_acl_table_group_member\n");
      status = sai_api_query(SAI_API_ACL, (void **) &acl_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      status = acl_api->remove_acl_table_group_member(acl_table_group_member_id);
	  if (status != SAI_STATUS_SUCCESS)
      {
          printf("remove acl table group member fail !\n");
      }
      return status;
  }

  void sai_thrift_get_acl_table_group_member_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t acl_table_group_member_id)
  {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_acl_api_t *acl_api;
      uint32_t attr_count = 0;
      sai_attribute_t attr_list[3];
      sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_ACL, (void **) &acl_api);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("failed to obtain acl_api, status:%d", status);
          return;
      }

      attr_list[0].id = SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_GROUP_ID;
      attr_list[1].id = SAI_ACL_TABLE_GROUP_MEMBER_ATTR_ACL_TABLE_ID;
      attr_list[2].id = SAI_ACL_TABLE_GROUP_MEMBER_ATTR_PRIORITY;
      attr_count = 3;

      status = acl_api->get_acl_table_group_member_attribute(acl_table_group_member_id, attr_count, attr_list);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("failed to obtain acl table group member attribute, status:%d", status);
          return;
      }

      thrift_attr.id = attr_list[0].id;
      thrift_attr.value.oid = attr_list[0].value.oid;
      thrift_attr_list.attr_list.push_back(thrift_attr);

	  thrift_attr.id = attr_list[1].id;
      thrift_attr.value.oid = attr_list[1].value.oid;
      thrift_attr_list.attr_list.push_back(thrift_attr);

	  thrift_attr.id = attr_list[2].id;
      thrift_attr.value.u32 = attr_list[2].value.u32;
      thrift_attr_list.attr_list.push_back(thrift_attr);

	  return;
  }

  sai_thrift_object_id_t sai_thrift_create_acl_counter(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      sai_object_id_t acl_counter_id = 0ULL;
      sai_acl_api_t *acl_api;
      sai_status_t status = SAI_STATUS_SUCCESS;
	  printf("sai_thrift_create_acl_counter\n");
      status = sai_api_query(SAI_API_ACL, (void **) &acl_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_convert_to_acl_counter_attributes(thrift_attr_list, attr_list);
      uint32_t attr_count = thrift_attr_list.size();
      status = acl_api->create_acl_counter(&acl_counter_id, gSwitchId, attr_count, attr_list);
      free(attr_list);
      return acl_counter_id;
  }

  sai_thrift_status_t sai_thrift_remove_acl_counter(const sai_thrift_object_id_t acl_counter_id) {
      sai_object_id_t acl_entry = 0ULL;
      sai_acl_api_t *acl_api;
      sai_status_t status = SAI_STATUS_SUCCESS;
	  printf("sai_thrift_remove_acl_counter\n");
      status = sai_api_query(SAI_API_ACL, (void **) &acl_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      status = acl_api->remove_acl_counter(acl_counter_id);
      return status;
  }

  void sai_thrift_get_acl_counter_attribute(
          std::vector<sai_thrift_attribute_value_t> & thrift_attr_values,
          const sai_thrift_object_id_t acl_counter_id,
          const std::vector<int32_t> & thrift_attr_ids) {
      sai_object_id_t acl_entry = 0ULL;
      sai_acl_api_t *acl_api;
      sai_status_t status = SAI_STATUS_SUCCESS;
	  printf("sai_thrift_get_acl_counter_attribute\n");
      status = sai_api_query(SAI_API_ACL, (void **) &acl_api);
      if (status != SAI_STATUS_SUCCESS) {
          return;
      }

      uint32_t attr_count = thrift_attr_ids.size();
      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_ids.size());
      memset(attr_list, 0x0, sizeof(sizeof(sai_attribute_t) * thrift_attr_ids.size()));
      sai_thrift_parse_attribute_ids(thrift_attr_ids, attr_list);
      status = acl_api->get_acl_counter_attribute(acl_counter_id, attr_count, attr_list);
      if (status != SAI_STATUS_SUCCESS) {
          return;
      }

      sai_thrift_convert_to_acl_thrift_counter_attributes(
                             attr_list,
                             attr_count,
                             thrift_attr_values);
      return;
  }

  void sai_thrift_parse_hash_attributes(const std::vector < sai_thrift_attribute_t > &thrift_attr_list, sai_attribute_t *attr_list, sai_int32_t **buffer_profile_list1, sai_object_id_t **buffer_profile_list2)
  {
      std::vector < sai_thrift_attribute_t > ::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for (uint32_t i = 0; i < thrift_attr_list.size(); i++, it++)
      {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;
          switch (attribute.id)
          {
              case SAI_HASH_ATTR_NATIVE_HASH_FIELD_LIST:
                  {
                      *buffer_profile_list1 = (int32_t *) malloc(sizeof(int32_t) * attribute.value.s32list.count);
                      std::vector<sai_int32_t>::const_iterator it2 = attribute.value.s32list.s32list.begin();
                      for (uint32_t j = 0; j < attribute.value.s32list.s32list.size(); j++, *it2++)
                      {
                          (*buffer_profile_list1)[j] = (sai_int32_t) *it2;
                      }
                      attr_list[i].value.s32list.count = attribute.value.s32list.count;
                      attr_list[i].value.s32list.list = *buffer_profile_list1;
                      break;
                  }
              case SAI_HASH_ATTR_UDF_GROUP_LIST:
                  {
                      *buffer_profile_list2 = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * attribute.value.objlist.count);
                      std::vector < sai_thrift_object_id_t > ::const_iterator it2 = attribute.value.objlist.object_id_list.begin();
                      for (uint32_t j = 0; j < attribute.value.objlist.object_id_list.size(); j++, *it2++)
                      {
                          (*buffer_profile_list2)[j] = (sai_object_id_t) *it2;
                      }
                      attr_list[i].value.objlist.count = attribute.value.objlist.count;
                      attr_list[i].value.objlist.list = *buffer_profile_list2;
                      break;
                  }
              default:
                  break;
          }
      }
  }

  sai_thrift_object_id_t sai_thrift_create_hash(const std::vector < sai_thrift_attribute_t > & thrift_attr_list)
  {
      printf("sai_thrift_create_hash\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_hash_api_t *hash_api;
      sai_object_id_t hash_id = 0;
      status = sai_api_query(SAI_API_HASH, (void **) &hash_api);
      if (status != SAI_STATUS_SUCCESS)
      {
          return status;
      }
      sai_int32_t     *buffer_profile_list1 = NULL;
      sai_object_id_t *buffer_profile_list2 = NULL;
      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parse_hash_attributes(thrift_attr_list, attr_list, &buffer_profile_list1, &buffer_profile_list2);
      uint32_t attr_count = thrift_attr_list.size();
      status = hash_api->create_hash(&hash_id, gSwitchId, attr_count, attr_list);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("failed to create hash, status:%d", status);
      }

      if (buffer_profile_list1)
      {
          free(buffer_profile_list1);
      }
      if (buffer_profile_list2)
      {
          free(buffer_profile_list2);
      }

      return hash_id;
  }

  sai_thrift_status_t sai_thrift_remove_hash(const sai_thrift_object_id_t hash_id)
  {
      printf("sai_thrift_remove_hash\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_hash_api_t *hash_api;
      status = sai_api_query(SAI_API_HASH, (void **) &hash_api);
      if (status != SAI_STATUS_SUCCESS)
      {
          return status;
      }
      status = hash_api->remove_hash((sai_object_id_t) hash_id);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to remove hash.");
      }
      return status;
  }

  sai_thrift_status_t sai_thrift_set_hash_attribute(const sai_thrift_object_id_t hash_id, const sai_thrift_attribute_t &thrift_attr)
  {
      printf("sai_thrift_set_hash_attribute\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_hash_api_t *hash_api;
      status = sai_api_query(SAI_API_HASH, (void **) &hash_api);
      if (status != SAI_STATUS_SUCCESS)
      {
          return status;
      }
      sai_int32_t     *buffer_profile_list1 = NULL;
      sai_object_id_t *buffer_profile_list2 = NULL;
      std::vector < sai_thrift_attribute_t > thrift_attr_list;
      thrift_attr_list.push_back(thrift_attr);
      sai_attribute_t attr;
      sai_thrift_parse_hash_attributes(thrift_attr_list, &attr, &buffer_profile_list1, &buffer_profile_list2);
      status = hash_api->set_hash_attribute((sai_object_id_t)hash_id, &attr);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to set hash attributes, status:%d", status);
      }
      if (buffer_profile_list1)
      {
          free(buffer_profile_list1);
      }
      if (buffer_profile_list2)
      {
          free(buffer_profile_list2);
      }
      return status;
  }

void sai_thrift_get_hash_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t hash_id)
{
    printf("sai_thrift_get_hash_attribute\n");
    sai_status_t status = SAI_STATUS_SUCCESS;
    sai_hash_api_t *hash_api;
    sai_attribute_t sai_attrs[SAI_HASH_ATTR_END];
    sai_thrift_attribute_t thrift_attr;
    uint8_t loop_i = 0;
    status = sai_api_query(SAI_API_HASH, (void **) &hash_api);
    if (status != SAI_STATUS_SUCCESS)
    {
        return;
    }

    for (loop_i = SAI_HASH_ATTR_START; loop_i < SAI_HASH_ATTR_END; loop_i++)
    {
        sai_attrs[loop_i].id = loop_i;
    }
    sai_attrs[SAI_HASH_ATTR_NATIVE_HASH_FIELD_LIST].id = SAI_HASH_ATTR_NATIVE_HASH_FIELD_LIST;
    sai_attrs[SAI_HASH_ATTR_NATIVE_HASH_FIELD_LIST].value.s32list.list = (int32_t *) malloc(sizeof(int32_t) * (SAI_NATIVE_HASH_FIELD_IN_PORT + 1));
    sai_attrs[SAI_HASH_ATTR_NATIVE_HASH_FIELD_LIST].value.s32list.count = SAI_NATIVE_HASH_FIELD_IN_PORT + 1;

    sai_attrs[SAI_HASH_ATTR_UDF_GROUP_LIST].id = SAI_HASH_ATTR_UDF_GROUP_LIST;
    sai_attrs[SAI_HASH_ATTR_UDF_GROUP_LIST].value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * 16);
    sai_attrs[SAI_HASH_ATTR_UDF_GROUP_LIST].value.objlist.count = 16;

    status = hash_api->get_hash_attribute(hash_id, SAI_HASH_ATTR_END, sai_attrs);
    if (status != SAI_STATUS_SUCCESS)
    {
        SAI_THRIFT_LOG_ERR("Failed to get hash attributes, status:%d", status);
        thrift_attr_list.status = status;
        return;
    }

    thrift_attr.id        = sai_attrs[0].id;  /* SAI_HASH_ATTR_NATIVE_HASH_FIELD_LIST */
    thrift_attr.value.s32list.count = sai_attrs[0].value.s32list.count;
    std::vector < sai_int32_t > & hash_field_list = thrift_attr.value.s32list.s32list;
    for (int index = 0; index < sai_attrs[0].value.s32list.count; index++)
    {
        hash_field_list.push_back((sai_int32_t) sai_attrs[0].value.s32list.list[index]);
    }
    thrift_attr_list.attr_list.push_back(thrift_attr);

    thrift_attr.id        = sai_attrs[1].id;  /* SAI_HASH_ATTR_UDF_GROUP_LIST */
    thrift_attr.value.objlist.count = sai_attrs[1].value.objlist.count;
    std::vector < sai_thrift_object_id_t > & udf_group_list = thrift_attr.value.objlist.object_id_list;
    for (int index = 0; index < sai_attrs[1].value.objlist.count; index++)
    {
        udf_group_list.push_back((sai_thrift_object_id_t) sai_attrs[1].value.objlist.list[index]);
    }
    thrift_attr_list.attr_list.push_back(thrift_attr);

    if (sai_attrs[SAI_HASH_ATTR_UDF_GROUP_LIST].value.objlist.list)
    {
        free(sai_attrs[SAI_HASH_ATTR_UDF_GROUP_LIST].value.objlist.list);
    }
    if (sai_attrs[SAI_HASH_ATTR_NATIVE_HASH_FIELD_LIST].value.s32list.list)
    {
        free(sai_attrs[SAI_HASH_ATTR_NATIVE_HASH_FIELD_LIST].value.s32list.list);
    }
}

  void sai_thrift_parse_udf_group_attributes(const std::vector < sai_thrift_attribute_t > &thrift_attr_list, sai_attribute_t *attr_list, sai_object_id_t **buffer_profile_list1)
  {
      std::vector < sai_thrift_attribute_t > ::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for (uint32_t i = 0; i < thrift_attr_list.size(); i++, it++)
      {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;
          switch (attribute.id)
          {
              case SAI_UDF_GROUP_ATTR_UDF_LIST: /* @flags READ_ONLY */
                  {
                      *buffer_profile_list1 = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * attribute.value.objlist.count);
                      std::vector < sai_thrift_object_id_t > ::const_iterator it2 = attribute.value.objlist.object_id_list.begin();
                      for (uint32_t j = 0; j < attribute.value.objlist.object_id_list.size(); j++, *it2++)
                      {
                          (*buffer_profile_list1)[j] = (sai_object_id_t) *it2;
                      }
                      attr_list[i].value.objlist.count = attribute.value.objlist.count;
                      attr_list[i].value.objlist.list = *buffer_profile_list1;
                      break;
                  }
              case SAI_UDF_GROUP_ATTR_TYPE:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
              case SAI_UDF_GROUP_ATTR_LENGTH:
                  attr_list[i].value.u16 = attribute.value.u16;
                  break;
              default:
                  break;
          }
      }
  }

  sai_thrift_object_id_t sai_thrift_create_udf_group(const std::vector < sai_thrift_attribute_t > & thrift_attr_list)
  {
      printf("sai_thrift_create_udf_group\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_udf_api_t *udf_api;
      sai_object_id_t udf_grp_id = 0;
      status = sai_api_query(SAI_API_UDF, (void **) &udf_api);
      if (status != SAI_STATUS_SUCCESS)
      {
          return status;
      }
      sai_object_id_t     *buffer_profile_list1 = NULL;
      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parse_udf_group_attributes(thrift_attr_list, attr_list, &buffer_profile_list1);
      uint32_t attr_count = thrift_attr_list.size();
      status = udf_api->create_udf_group(&udf_grp_id, gSwitchId, attr_count, attr_list);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("failed to create udf group, status:%d", status);
      }
      if (buffer_profile_list1)
      {
          free(buffer_profile_list1);
      }

      return udf_grp_id;
  }

    sai_thrift_status_t sai_thrift_remove_udf_group(const sai_thrift_object_id_t udf_group_id)
    {
        printf("sai_thrift_remove_udf_group\n");
        sai_status_t status = SAI_STATUS_SUCCESS;
        sai_udf_api_t *udf_api;
        status = sai_api_query(SAI_API_UDF, (void **) &udf_api);
        if (status != SAI_STATUS_SUCCESS)
        {
            return status;
        }
        status = udf_api->remove_udf_group((sai_object_id_t) udf_group_id);
        if (status != SAI_STATUS_SUCCESS)
        {
            SAI_THRIFT_LOG_ERR("Failed to remove udf group.");
        }
        return status;
    }

void sai_thrift_get_udf_group_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t udf_group_id)
{
    printf("sai_thrift_get_udf_group_attribute\n");
    sai_status_t status = SAI_STATUS_SUCCESS;
    sai_udf_api_t *udf_api;
    sai_attribute_t sai_attrs[SAI_UDF_GROUP_ATTR_END];
    sai_thrift_attribute_t thrift_attr;
    uint8_t loop_i = 0;
    status = sai_api_query(SAI_API_UDF, (void **) &udf_api);
    if (status != SAI_STATUS_SUCCESS)
    {
        return;
    }

    for (loop_i = SAI_UDF_GROUP_ATTR_START; loop_i < SAI_UDF_GROUP_ATTR_END; loop_i++)
    {
        sai_attrs[loop_i].id = loop_i;
    }

    sai_attrs[SAI_UDF_GROUP_ATTR_UDF_LIST].id = SAI_UDF_GROUP_ATTR_UDF_LIST;
    sai_attrs[SAI_UDF_GROUP_ATTR_UDF_LIST].value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * 4);
    sai_attrs[SAI_UDF_GROUP_ATTR_UDF_LIST].value.objlist.count = 4;

    status = udf_api->get_udf_group_attribute(udf_group_id, SAI_UDF_GROUP_ATTR_END, sai_attrs);
    if (status != SAI_STATUS_SUCCESS)
    {
        SAI_THRIFT_LOG_ERR("Failed to get udf group attributes, status:%d", status);
        thrift_attr_list.status = status;
        return;
    }

    thrift_attr.id        = sai_attrs[0].id;  /* SAI_UDF_GROUP_ATTR_UDF_LIST */
    thrift_attr.value.objlist.count = sai_attrs[0].value.objlist.count;
    std::vector < sai_thrift_object_id_t > & udf_list = thrift_attr.value.objlist.object_id_list;
    for (int index = 0; index < sai_attrs[0].value.objlist.count; index++)
    {
        udf_list.push_back((sai_thrift_object_id_t) sai_attrs[0].value.objlist.list[index]);
    }
    thrift_attr_list.attr_list.push_back(thrift_attr);

    thrift_attr.id        = sai_attrs[1].id;   /* SAI_UDF_GROUP_ATTR_TYPE */
    thrift_attr.value.s32 = sai_attrs[1].value.s32;
    thrift_attr_list.attr_list.push_back(thrift_attr);

    thrift_attr.id        = sai_attrs[2].id;   /* SAI_UDF_GROUP_ATTR_LENGTH */
    thrift_attr.value.u16 = sai_attrs[2].value.u16;
    thrift_attr_list.attr_list.push_back(thrift_attr);

    if (sai_attrs[SAI_UDF_GROUP_ATTR_UDF_LIST].value.objlist.list)
    {
        free(sai_attrs[SAI_UDF_GROUP_ATTR_UDF_LIST].value.objlist.list);
    }

}

  void sai_thrift_parse_udf_match_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list)
  {
      std::vector < sai_thrift_attribute_t > ::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for (uint32_t i = 0; i < thrift_attr_list.size(); i++, it++)
      {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;
          switch (attribute.id)
          {
              case SAI_UDF_MATCH_ATTR_L2_TYPE:
                  attr_list[i].value.aclfield.data.u16 = attribute.value.aclfield.data.u16;
                  attr_list[i].value.aclfield.mask.u16 = attribute.value.aclfield.mask.u16;
                  break;
              case SAI_UDF_MATCH_ATTR_L3_TYPE:
                  attr_list[i].value.aclfield.data.u8 = attribute.value.aclfield.data.u8;
                  attr_list[i].value.aclfield.mask.u8 = attribute.value.aclfield.mask.u8;
                  break;
              case SAI_UDF_MATCH_ATTR_GRE_TYPE:
                  attr_list[i].value.aclfield.data.u16 = attribute.value.aclfield.data.u16;
                  attr_list[i].value.aclfield.mask.u16 = attribute.value.aclfield.mask.u16;
                  break;
              case SAI_UDF_MATCH_ATTR_PRIORITY:
                  attr_list[i].value.u8 = attribute.value.u8;
                  break;
              default:
                  break;
          }
      }
  }

  sai_thrift_object_id_t sai_thrift_create_udf_match(const std::vector < sai_thrift_attribute_t > & thrift_attr_list)
  {
      printf("sai_thrift_create_udf_match\n");
      sai_object_id_t udf_match_id = 0;
      sai_udf_api_t *udf_api;
      sai_status_t status = SAI_STATUS_SUCCESS;
      status = sai_api_query(SAI_API_UDF, (void **) &udf_api);
      if (status != SAI_STATUS_SUCCESS)
      {
          return status;
      }

      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parse_udf_match_attributes(thrift_attr_list, attr_list);
      uint32_t attr_count = thrift_attr_list.size();
      status = udf_api->create_udf_match(&udf_match_id, gSwitchId, attr_count, attr_list);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("failed to create udf match, status:%d", status);
      }
      free(attr_list);
      return udf_match_id;
  }

  sai_thrift_status_t sai_thrift_remove_udf_match(const sai_thrift_object_id_t udf_match_id)
  {
      printf("sai_thrift_remove_udf_match\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_udf_api_t *udf_api;
      status = sai_api_query(SAI_API_UDF, (void **) &udf_api);
      if (status != SAI_STATUS_SUCCESS)
      {
          return status;
      }
      status = udf_api->remove_udf_match((sai_object_id_t) udf_match_id);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to remove udf match.");
      }
      return status;
  }

  void sai_thrift_get_udf_match_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t udf_match_id)
  {
      printf("sai_thrift_get_udf_match_attribute\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_udf_api_t *udf_api;
      sai_attribute_t sai_attrs[SAI_UDF_MATCH_ATTR_END];
      sai_thrift_attribute_t thrift_attr;
      uint8_t loop_i = 0;
      status = sai_api_query(SAI_API_UDF, (void **) &udf_api);
      if (status != SAI_STATUS_SUCCESS)
      {
          return;
      }

      for (loop_i = SAI_UDF_MATCH_ATTR_START; loop_i < SAI_UDF_MATCH_ATTR_END; loop_i++)
      {
          sai_attrs[loop_i].id = loop_i;
      }

      status = udf_api->get_udf_match_attribute(udf_match_id, SAI_UDF_MATCH_ATTR_END, sai_attrs);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to get udf match attributes, status:%d", status);
          thrift_attr_list.status = status;
          return;
      }

      thrift_attr.id        = sai_attrs[0].id;   /* SAI_UDF_MATCH_ATTR_L2_TYPE */
      thrift_attr.value.aclfield.data.u16 = sai_attrs[0].value.aclfield.data.u16;
      thrift_attr.value.aclfield.mask.u16 = sai_attrs[0].value.aclfield.mask.u16;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[1].id;  /* SAI_UDF_MATCH_ATTR_L3_TYPE */
      thrift_attr.value.aclfield.data.u8 = sai_attrs[1].value.aclfield.data.u8;
      thrift_attr.value.aclfield.mask.u8 = sai_attrs[1].value.aclfield.mask.u8;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[2].id;  /* SAI_UDF_MATCH_ATTR_GRE_TYPE */
      thrift_attr.value.aclfield.data.u16 = sai_attrs[2].value.aclfield.data.u16;
      thrift_attr.value.aclfield.mask.u16 = sai_attrs[2].value.aclfield.mask.u16;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[3].id;  /* SAI_UDF_MATCH_ATTR_PRIORITY */
      thrift_attr.value.u8 = sai_attrs[3].value.u8;
      thrift_attr_list.attr_list.push_back(thrift_attr);
  }

  void sai_thrift_parse_udf_attributes(const std::vector < sai_thrift_attribute_t > &thrift_attr_list, sai_attribute_t *attr_list, sai_uint8_t **buffer_profile_list1)
  {
      std::vector < sai_thrift_attribute_t > ::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for (uint32_t i = 0; i < thrift_attr_list.size(); i++, it++)
      {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;
          switch (attribute.id)
          {
              case SAI_UDF_ATTR_MATCH_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;
              case SAI_UDF_ATTR_GROUP_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;
              case SAI_UDF_ATTR_BASE:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
              case SAI_UDF_ATTR_OFFSET:
                  attr_list[i].value.u16 = attribute.value.u16 ;
                  break;
              case SAI_UDF_ATTR_HASH_MASK:
                  {
                      *buffer_profile_list1 = (sai_uint8_t *) malloc(sizeof(sai_uint8_t) * attribute.value.u8list.count);
                      std::vector <sai_int8_t> ::const_iterator it2 = attribute.value.u8list.u8list.begin();
                      for (uint32_t j = 0; j < attribute.value.u8list.u8list.size(); j++, *it2++)
                      {
                          (*buffer_profile_list1)[j] = (sai_uint8_t) *it2;
                      }
                      attr_list[i].value.u8list.count = attribute.value.u8list.count;
                      attr_list[i].value.u8list.list = *buffer_profile_list1;
                      break;
                  }
              default:
                  break;
          }
      }
  }

  sai_thrift_object_id_t sai_thrift_create_udf(const std::vector < sai_thrift_attribute_t > & thrift_attr_list)
  {
      printf("sai_thrift_create_udf\n");
      sai_object_id_t udf_id = 0;
      sai_udf_api_t *udf_api;
      sai_status_t status = SAI_STATUS_SUCCESS;
      status = sai_api_query(SAI_API_UDF, (void **) &udf_api);
      if (status != SAI_STATUS_SUCCESS)
      {
          return status;
      }

      sai_uint8_t     *buffer_profile_list1 = NULL;
      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parse_udf_attributes(thrift_attr_list, attr_list, &buffer_profile_list1);
      uint32_t attr_count = thrift_attr_list.size();
      status = udf_api->create_udf(&udf_id, gSwitchId, attr_count, attr_list);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("failed to create udf, status:%d", status);
      }
      free(attr_list);
      if (buffer_profile_list1)
      {
          free(buffer_profile_list1);
      }
      return udf_id;
  }

  sai_thrift_status_t sai_thrift_remove_udf(const sai_thrift_object_id_t udf_id)
  {
      printf("sai_thrift_remove_udf\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_udf_api_t *udf_api;
      status = sai_api_query(SAI_API_UDF, (void **) &udf_api);
      if (status != SAI_STATUS_SUCCESS)
      {
          return status;
      }
      status = udf_api->remove_udf((sai_object_id_t) udf_id);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to remove udf, status:%d", status);
      }
      return status;
  }

    sai_thrift_status_t sai_thrift_set_udf_attribute(const sai_thrift_object_id_t udf_id, const sai_thrift_attribute_t &thrift_attr)
    {
        printf("sai_thrift_set_udf\n");
        sai_status_t status = SAI_STATUS_SUCCESS;
        sai_udf_api_t *udf_api;
        status = sai_api_query(SAI_API_UDF, (void **) &udf_api);
        if (status != SAI_STATUS_SUCCESS)
        {
            return status;
        }

        sai_uint8_t     *buffer_profile_list1 = NULL;
        std::vector < sai_thrift_attribute_t > thrift_attr_list;
        thrift_attr_list.push_back(thrift_attr);
        sai_attribute_t attr;
        sai_thrift_parse_udf_attributes(thrift_attr_list, &attr, &buffer_profile_list1);
        status = udf_api->set_udf_attribute((sai_object_id_t)udf_id, &attr);
        if (status != SAI_STATUS_SUCCESS)
        {
            SAI_THRIFT_LOG_ERR("Failed to set udf attributes, status:%d", status);
        }
        if (buffer_profile_list1)
        {
            free(buffer_profile_list1);
        }
        return status;
    }

  void sai_thrift_get_udf_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t udf_id)
  {
      printf("sai_thrift_get_udf_attribute\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_udf_api_t *udf_api;
      sai_attribute_t sai_attrs[SAI_UDF_ATTR_END];
      sai_thrift_attribute_t thrift_attr;
      uint8_t loop_i = 0;
      status = sai_api_query(SAI_API_UDF, (void **) &udf_api);
      if (status != SAI_STATUS_SUCCESS)
      {
          return;
      }

      for (loop_i = SAI_UDF_ATTR_START; loop_i < SAI_UDF_ATTR_END; loop_i++)
      {
          sai_attrs[loop_i].id = loop_i;
      }
      sai_attrs[SAI_UDF_ATTR_HASH_MASK].id = SAI_UDF_ATTR_HASH_MASK;
      sai_attrs[SAI_UDF_ATTR_HASH_MASK].value.u8list.list = (uint8_t *) malloc(sizeof(uint8_t) * 4);
      sai_attrs[SAI_UDF_ATTR_HASH_MASK].value.u8list.count = 4;

      status = udf_api->get_udf_attribute(udf_id, SAI_UDF_ATTR_END, sai_attrs);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to get udf attributes, status:%d", status);
          thrift_attr_list.status = status;
          return;
      }

      thrift_attr.id        = sai_attrs[0].id;  /* SAI_UDF_ATTR_MATCH_ID */
      thrift_attr.value.oid = sai_attrs[0].value.oid;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[1].id;  /* SAI_UDF_ATTR_GROUP_ID */
      thrift_attr.value.oid = sai_attrs[1].value.oid;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[2].id;  /* SAI_UDF_ATTR_BASE */
      thrift_attr.value.s32 = sai_attrs[2].value.s32;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[3].id;  /* SAI_UDF_ATTR_OFFSET */
      thrift_attr.value.u16 = sai_attrs[3].value.u16;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[4].id;  /* SAI_UDF_ATTR_HASH_MASK */
      thrift_attr.value.u8list.count = sai_attrs[4].value.u8list.count;
      std::vector < sai_int8_t > & udf_list = thrift_attr.value.u8list.u8list;
      for (int index = 0; index < sai_attrs[4].value.u8list.count; index++)
      {
          udf_list.push_back((sai_uint8_t) sai_attrs[4].value.u8list.list[index]);
      }
      thrift_attr_list.attr_list.push_back(thrift_attr);

      if (sai_attrs[SAI_UDF_ATTR_HASH_MASK].value.u8list.list)
      {
          free (sai_attrs[SAI_UDF_ATTR_HASH_MASK].value.u8list.list);
      }

  }

  void sai_thrift_parse_mirror_session_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list)
  {
      std::vector < sai_thrift_attribute_t > ::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for (uint32_t i = 0; i < thrift_attr_list.size(); i++, it++)
      {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;
          switch (attribute.id)
          {
              case SAI_MIRROR_SESSION_ATTR_TYPE:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
              case SAI_MIRROR_SESSION_ATTR_MONITOR_PORT:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;
              case SAI_MIRROR_SESSION_ATTR_TRUNCATE_SIZE:
                  attr_list[i].value.u16 = attribute.value.u16;
                  break;
              case SAI_MIRROR_SESSION_ATTR_SAMPLE_RATE:
                  attr_list[i].value.u32 = attribute.value.u32;
                  break;
              case SAI_MIRROR_SESSION_ATTR_TC:
                  attr_list[i].value.u8 = attribute.value.u8;
                  break;
              case SAI_MIRROR_SESSION_ATTR_VLAN_TPID:
                  attr_list[i].value.u16 = attribute.value.u16;
                  break;
              case SAI_MIRROR_SESSION_ATTR_VLAN_ID:
                  attr_list[i].value.u16 = attribute.value.u16;
                  break;
              case SAI_MIRROR_SESSION_ATTR_VLAN_PRI:
                  attr_list[i].value.u8 = attribute.value.u8;
                  break;
              case SAI_MIRROR_SESSION_ATTR_VLAN_CFI:
                  attr_list[i].value.u8 = attribute.value.u8;
                  break;
              case SAI_MIRROR_SESSION_ATTR_VLAN_HEADER_VALID:
                  attr_list[i].value.booldata = attribute.value.booldata;
                  break;
              case SAI_MIRROR_SESSION_ATTR_ERSPAN_ENCAPSULATION_TYPE:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
              case SAI_MIRROR_SESSION_ATTR_IPHDR_VERSION:
                  attr_list[i].value.u8 = attribute.value.u8;
                  break;
              case SAI_MIRROR_SESSION_ATTR_TOS:
                  attr_list[i].value.u8 = attribute.value.u8;
                  break;
              case SAI_MIRROR_SESSION_ATTR_TTL:
                  attr_list[i].value.u8 = attribute.value.u8;
                  break;
              case SAI_MIRROR_SESSION_ATTR_SRC_IP_ADDRESS:
                  sai_thrift_parse_ip_address(attribute.value.ipaddr, &attr_list[i].value.ipaddr);
                  break;
              case SAI_MIRROR_SESSION_ATTR_DST_IP_ADDRESS:
                  sai_thrift_parse_ip_address(attribute.value.ipaddr, &attr_list[i].value.ipaddr);
                  break;
              case SAI_MIRROR_SESSION_ATTR_SRC_MAC_ADDRESS:
                  sai_thrift_string_to_mac(attribute.value.mac, attr_list[i].value.mac);
                  break;
              case SAI_MIRROR_SESSION_ATTR_DST_MAC_ADDRESS:
                  sai_thrift_string_to_mac(attribute.value.mac, attr_list[i].value.mac);
                  break;
              case SAI_MIRROR_SESSION_ATTR_GRE_PROTOCOL_TYPE:
                  attr_list[i].value.u16 = attribute.value.u16;
                  break;
              default:
                  break;
          }
      }
  }

  sai_thrift_object_id_t sai_thrift_create_mirror_session(const std::vector<sai_thrift_attribute_t> & thrift_attr_list)
  {
      printf("sai_thrift_create_mirror_session\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_mirror_api_t *mirror_api;
      sai_object_id_t session_id = 0;
      status = sai_api_query(SAI_API_MIRROR, (void **) &mirror_api);
      if (status != SAI_STATUS_SUCCESS)
      {
          return status;
      }
      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parse_mirror_session_attributes(thrift_attr_list, attr_list);
      uint32_t attr_count = thrift_attr_list.size();
      status = mirror_api->create_mirror_session(&session_id, gSwitchId, attr_count, attr_list);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("failed to create mirror session, status:%d", status);
      }
      free (attr_list);
      return session_id;
  }

  sai_thrift_status_t sai_thrift_remove_mirror_session(const sai_thrift_object_id_t session_id)
  {
      printf("sai_thrift_remove_mirror_session\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_mirror_api_t *mirror_api;
      status = sai_api_query(SAI_API_MIRROR, (void **) &mirror_api);
      if (status != SAI_STATUS_SUCCESS)
      {
          return status;
      }
      status = mirror_api->remove_mirror_session((sai_object_id_t) session_id);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to remove mirror session.");
      }
      return status;
  }

  sai_thrift_status_t sai_thrift_set_mirror_attribute(const sai_thrift_object_id_t mirror_id, const sai_thrift_attribute_t &thrift_attr)
  {
      printf("sai_thrift_set_mirror\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_mirror_api_t *mirror_api;
      status = sai_api_query(SAI_API_MIRROR, (void **) &mirror_api);
      if (status != SAI_STATUS_SUCCESS)
      {
          return status;
      }

      std::vector < sai_thrift_attribute_t > thrift_attr_list;
      thrift_attr_list.push_back(thrift_attr);

      sai_attribute_t *attr_list = nullptr;
      sai_uint32_t attr_size = 1;
      sai_thrift_alloc_attr(attr_list, attr_size);
      sai_thrift_parse_mirror_session_attributes(thrift_attr_list, attr_list);
      status = mirror_api->set_mirror_session_attribute((sai_object_id_t)mirror_id, attr_list);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to set mirror attributes.");
      }
      return status;
  }

  void sai_thrift_get_mirror_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t mirror_id)
  {
      printf("sai_thrift_get_mirror_attribute\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_mirror_api_t *mirror_api;
      sai_attribute_t sai_attrs[SAI_MIRROR_SESSION_ATTR_END];
      int array_index = 0;
      sai_thrift_attribute_t thrift_attr;
      int attribute_i = 0;
      status = sai_api_query(SAI_API_MIRROR, (void **) &mirror_api);
      if (status != SAI_STATUS_SUCCESS)
      {
          return;
      }
      /* SAI_MIRROR_SESSION_ATTR_TC NOT SUPPORT, trunk:sai1.3 SAI_MIRROR_SESSION_ATTR_SAMPLE_RATE new add */
      for (attribute_i = SAI_MIRROR_SESSION_ATTR_START; attribute_i < SAI_MIRROR_SESSION_ATTR_END; attribute_i++)
      {
          if ((SAI_MIRROR_SESSION_ATTR_TC == attribute_i) || (SAI_MIRROR_SESSION_ATTR_POLICER == attribute_i))
          {
              continue;
          }
          sai_attrs[array_index++].id = attribute_i;
      }

      status = mirror_api->get_mirror_session_attribute(mirror_id, array_index, sai_attrs);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to get mirror attributes, status:%d", status);
          thrift_attr_list.status = status;
          return;
      }

      thrift_attr.id        = sai_attrs[0].id;
      thrift_attr.value.s32 = sai_attrs[0].value.s32;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[1].id;
      thrift_attr.value.oid = sai_attrs[1].value.oid;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[2].id;
      thrift_attr.value.u16 = sai_attrs[2].value.u16;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[3].id;
      thrift_attr.value.u32 = sai_attrs[3].value.u32;
      thrift_attr_list.attr_list.push_back(thrift_attr);  /* trunk:sai1.3 SAI_MIRROR_SESSION_ATTR_SAMPLE_RATE new add */


      thrift_attr.id        = sai_attrs[4].id;
      thrift_attr.value.s32 = sai_attrs[4].value.s32;
      thrift_attr_list.attr_list.push_back(thrift_attr); /* trunk:sai1.3 SAI_MIRROR_SESSION_ATTR_CONGESTION_MODE new add */

      thrift_attr.id        = sai_attrs[5].id;
      thrift_attr.value.u16 = sai_attrs[5].value.u16;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[6].id;
      thrift_attr.value.u16 = sai_attrs[6].value.u16;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[7].id;
      thrift_attr.value.u8 = sai_attrs[7].value.u8;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[8].id;
      thrift_attr.value.u8 = sai_attrs[8].value.u8;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[9].id;
      thrift_attr.value.booldata = sai_attrs[9].value.booldata;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[10].id;
      thrift_attr.value.s32 = sai_attrs[10].value.s32;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[11].id;
      thrift_attr.value.u8 = sai_attrs[11].value.u8;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[12].id;
      thrift_attr.value.u8 = sai_attrs[12].value.u8;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[13].id;
      thrift_attr.value.u8 = sai_attrs[13].value.u8;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[14].id;
      thrift_attr.value.ipaddr.addr_family = sai_attrs[14].value.ipaddr.addr_family;
      if (SAI_IP_ADDR_FAMILY_IPV4 == thrift_attr.value.ipaddr.addr_family)
      {
          thrift_attr.value.ipaddr.addr.ip4 = sai_thrift_v4_ip_to_string(sai_attrs[14].value.ipaddr.addr.ip4);
      }
      else
      {

      }
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[15].id;
      thrift_attr.value.ipaddr.addr_family = sai_attrs[15].value.ipaddr.addr_family;
      if (SAI_IP_ADDR_FAMILY_IPV4 == thrift_attr.value.ipaddr.addr_family)
      {
          thrift_attr.value.ipaddr.addr.ip4 = sai_thrift_v4_ip_to_string(sai_attrs[15].value.ipaddr.addr.ip4);
      }
      else
      {

      }
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[16].id;
      thrift_attr.value.mac = sai_thrift_mac_to_string(sai_attrs[16].value.mac);
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[17].id;
      thrift_attr.value.mac = sai_thrift_mac_to_string(sai_attrs[17].value.mac);
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = sai_attrs[18].id;
      thrift_attr.value.u16 = sai_attrs[18].value.u16;
      thrift_attr_list.attr_list.push_back(thrift_attr);
  }

sai_thrift_status_t
sai_thrift_create_inseg_entry(const sai_thrift_inseg_entry_t &thrift_inseg_entry, const std::vector<sai_thrift_attribute_t> & thrift_attr_list)
  {
      printf("sai_thrift_create_inseg_entry\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_mpls_api_t *mpls_api;
      sai_inseg_entry_t inseg_entry;
      status = sai_api_query(SAI_API_MPLS, (void **) &mpls_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_thrift_parser_inseg_entry(thrift_inseg_entry, &inseg_entry);
      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parser_mpls_attributes(thrift_attr_list, attr_list);
      uint32_t attr_count = thrift_attr_list.size();
      status = mpls_api->create_inseg_entry(&inseg_entry, attr_count, attr_list);
      free(attr_list);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to sai_thrift_create_inseg_entry, status:%d", status);
      }
      return status;
  }

sai_thrift_status_t
sai_thrift_remove_inseg_entry(const sai_thrift_inseg_entry_t &thrift_inseg_entry) {
      printf("sai_thrift_remove_inseg_entry\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_mpls_api_t *mpls_api;
      sai_inseg_entry_t inseg_entry;
      status = sai_api_query(SAI_API_MPLS, (void **) &mpls_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_thrift_parser_inseg_entry(thrift_inseg_entry, &inseg_entry);
      status = mpls_api->remove_inseg_entry(&inseg_entry);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to sai_thrift_remove_inseg_entry, status:%d", status);
      }
      return status;
  }

sai_thrift_status_t
sai_thrift_set_inseg_entry_attribute(const sai_thrift_inseg_entry_t &thrift_inseg_entry, const sai_thrift_attribute_t& thrift_attr) {
      printf("sai_thrift_set_inseg_entry_attributes\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };
      sai_mpls_api_t *mpls_api;
      sai_inseg_entry_t inseg_entry;
      sai_attribute_t *attr_list = nullptr;
      status = sai_api_query(SAI_API_MPLS, (void **) &mpls_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_thrift_alloc_attr(attr_list, 1);
      sai_thrift_parser_inseg_entry(thrift_inseg_entry, &inseg_entry);
      sai_thrift_parser_mpls_attributes(thrift_attr_list, attr_list);
      status = mpls_api->set_inseg_entry_attribute(&inseg_entry, attr_list);
      sai_thrift_free_attr(attr_list);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to sai_thrift_set_inseg_entry_attribute, status:%d", status);
      }
      return status;
  }

void sai_thrift_get_inseg_entry_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_inseg_entry_t &thrift_inseg_entry)
{
    printf("sai_thrift_get_inseg_entry_attribute\n");
    sai_status_t status = SAI_STATUS_SUCCESS;
    sai_mpls_api_t *mpls_api;
    sai_inseg_entry_t inseg_entry;
    sai_attribute_t attr[SAI_INSEG_ENTRY_ATTR_END];
    sai_thrift_attribute_t thrift_attr;
    uint32_t attr_cnt = 0;

    status = sai_api_query(SAI_API_MPLS, (void **) &mpls_api);
    if (status != SAI_STATUS_SUCCESS)
    {
        thrift_attr_list.status = status;
        return;
    }

    sai_thrift_parser_inseg_entry(thrift_inseg_entry, &inseg_entry);

    attr[attr_cnt++].id = SAI_INSEG_ENTRY_ATTR_NUM_OF_POP;
    attr[attr_cnt++].id = SAI_INSEG_ENTRY_ATTR_PACKET_ACTION;
    /* SAI_INSEG_ENTRY_ATTR_TRAP_PRIORITY not support */
    attr[attr_cnt++].id = SAI_INSEG_ENTRY_ATTR_NEXT_HOP_ID;

    status = mpls_api->get_inseg_entry_attribute(&inseg_entry, attr_cnt, attr);
    if (status != SAI_STATUS_SUCCESS)
    {
        SAI_THRIFT_LOG_ERR("Failed to sai_thrift_get_inseg_entry_attribute, status:%d", status);
        thrift_attr_list.status = status;
        return;
    }

    thrift_attr.id        = attr[0].id;                 /* SAI_INSEG_ENTRY_ATTR_NUM_OF_POP */
    thrift_attr.value.u8 = attr[0].value.u8;
    thrift_attr_list.attr_list.push_back(thrift_attr);

    thrift_attr.id        = attr[1].id;                 /* SAI_INSEG_ENTRY_ATTR_PACKET_ACTION */
    thrift_attr.value.s32 = attr[1].value.s32;
    thrift_attr_list.attr_list.push_back(thrift_attr);

    thrift_attr.id        = attr[2].id;                 /* SAI_INSEG_ENTRY_ATTR_NEXT_HOP_ID */
    thrift_attr.value.oid = attr[2].value.oid;
    thrift_attr_list.attr_list.push_back(thrift_attr);
}

  sai_thrift_status_t
  sai_thrift_dump_log(const std::string& dump_file_name)
  {
      printf("sai_thrift_dump_log\n");

      sai_status_t status = SAI_STATUS_SUCCESS;
      char file_name[DUMP_FILE_NAME_LEN] = {0};

      if (dump_file_name.length() > DUMP_FILE_NAME_LEN - 1)
      {
          SAI_THRIFT_LOG_ERR("dump_file_name is longer than DUMP_FILE_NAME_LEN, dump_file_name's max length is 50 byte");
          return SAI_STATUS_INVALID_PARAMETER;
      }

      strcpy(file_name, dump_file_name.c_str());

      status = sai_dbg_generate_dump(file_name);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to sai_thrift_dump_log, status:%d", status);
          return status;
      }

      return status;
  }

  void sai_thrift_parse_policer_attributes(sai_attribute_t *attr_list,
                                           const std::vector<sai_thrift_attribute_t> &thrift_attr_list) const noexcept
  {
      if (attr_list == nullptr || thrift_attr_list.empty())
      { SAI_THRIFT_LOG_ERR("Invalid input arguments."); return; }

      std::vector<sai_thrift_attribute_t>::const_iterator cit = thrift_attr_list.begin();

      for (sai_size_t i = 0; i < thrift_attr_list.size(); i++, cit++)
      {
          sai_thrift_attribute_t attribute = *cit;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
              case SAI_POLICER_ATTR_METER_TYPE:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
              case SAI_POLICER_ATTR_MODE:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
              case SAI_POLICER_ATTR_COLOR_SOURCE:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
              case SAI_POLICER_ATTR_CBS:
                  attr_list[i].value.u64 = attribute.value.u64;
                  break;
              case SAI_POLICER_ATTR_CIR:
                  attr_list[i].value.u64 = attribute.value.u64;
                  break;
              case SAI_POLICER_ATTR_PBS:
                  attr_list[i].value.u64 = attribute.value.u64;
                  break;
              case SAI_POLICER_ATTR_PIR:
                  attr_list[i].value.u64 = attribute.value.u64;
                  break;
              case SAI_POLICER_ATTR_GREEN_PACKET_ACTION:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
              case SAI_POLICER_ATTR_YELLOW_PACKET_ACTION:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
              case SAI_POLICER_ATTR_RED_PACKET_ACTION:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
              case SAI_POLICER_ATTR_ENABLE_COUNTER_PACKET_ACTION_LIST:
                  for (sai_size_t j = 0; j < attribute.value.s32list.s32list.size(); j++)
                  { attr_list[i].value.s32list.list[j] = attribute.value.s32list.s32list[j]; }
                  attr_list[i].value.s32list.count = attribute.value.s32list.s32list.size();
                  break;
              default:
                  SAI_THRIFT_LOG_ERR("Failed to parse attribute.");
                  break;
          }
      }
  }

  sai_thrift_object_id_t sai_thrift_create_policer(const std::vector<sai_thrift_attribute_t> &thrift_attr_list) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_policer_api_t *policer_api = nullptr;
      auto status = sai_api_query(SAI_API_POLICER, reinterpret_cast<void**>(&policer_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return SAI_NULL_OBJECT_ID; }

      sai_attribute_t *attr_list = nullptr;
      sai_size_t attr_size = thrift_attr_list.size();

      sai_thrift_alloc_array(attr_list, attr_size);
      sai_thrift_parse_policer_attributes(attr_list, thrift_attr_list);

      sai_object_id_t policer_oid = 0;
      status = policer_api->create_policer(&policer_oid, gSwitchId, attr_size, attr_list);
      sai_thrift_free_array(attr_list);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return policer_oid; }

      SAI_THRIFT_LOG_ERR("Failed to create OID.");

      return SAI_NULL_OBJECT_ID;
  }

  sai_thrift_status_t sai_thrift_remove_policer(const sai_thrift_object_id_t thrift_policer_id) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_policer_api_t *policer_api = nullptr;
      auto status = sai_api_query(SAI_API_POLICER, reinterpret_cast<void**>(&policer_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return status; }

      status = policer_api->remove_policer(thrift_policer_id);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return status; }

      SAI_THRIFT_LOG_ERR("Failed to remove OID.");

      return status;
  }

    void sai_thrift_get_policer_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t thrift_policer_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_policer_api_t *policer_api;
      uint32_t attr_count = 0;
      sai_attribute_t attr[10];
	  sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_POLICER, (void **) &policer_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain policer_api, status:%d", status);
          return;
      }

      attr[0].id = SAI_POLICER_ATTR_METER_TYPE;
      attr[1].id = SAI_POLICER_ATTR_MODE;
	  attr[2].id = SAI_POLICER_ATTR_COLOR_SOURCE;
	  attr[3].id = SAI_POLICER_ATTR_CBS;
      attr[4].id = SAI_POLICER_ATTR_CIR;
	  attr[5].id = SAI_POLICER_ATTR_PBS;
	  attr[6].id = SAI_POLICER_ATTR_PIR;
      attr[7].id = SAI_POLICER_ATTR_GREEN_PACKET_ACTION;
	  attr[8].id = SAI_POLICER_ATTR_YELLOW_PACKET_ACTION;
	  attr[9].id = SAI_POLICER_ATTR_RED_PACKET_ACTION;
      attr_count = 10;

      status = policer_api->get_policer_attribute(thrift_policer_id, attr_count, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to get policer attr, status:%d", status);
          return;
      }

	  thrift_attr.id = attr[0].id;
	  thrift_attr.value.u32 = attr[0].value.u32;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[1].id;
	  thrift_attr.value.u32 = attr[1].value.u32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[2].id;
	  thrift_attr.value.u32 = attr[2].value.u32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[3].id;
	  thrift_attr.value.u64 = attr[3].value.u64;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[4].id;
	  thrift_attr.value.u64 = attr[4].value.u64;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[5].id;
	  thrift_attr.value.u64 = attr[5].value.u64;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[6].id;
	  thrift_attr.value.u64 = attr[6].value.u64;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
  	  thrift_attr.id = attr[7].id;
	  thrift_attr.value.u32 = attr[7].value.u32;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[8].id;
	  thrift_attr.value.u32 = attr[8].value.u32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[9].id;
	  thrift_attr.value.u32 = attr[9].value.u32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
  }

  sai_thrift_status_t sai_thrift_set_policer_attribute(const sai_thrift_object_id_t thrift_policer_id, const sai_thrift_attribute_t &thrift_attr) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_policer_api_t *policer_api = nullptr;
      auto status = sai_api_query(SAI_API_POLICER, reinterpret_cast<void**>(&policer_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return status; }

      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      sai_attribute_t *attr_list = nullptr;
      sai_size_t attr_size = thrift_attr_list.size();

      sai_thrift_alloc_array(attr_list, attr_size);
      sai_thrift_parse_policer_attributes(attr_list, thrift_attr_list);

      status = policer_api->set_policer_attribute(thrift_policer_id, attr_list);
      sai_thrift_free_array(attr_list);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return status; }

      SAI_THRIFT_LOG_ERR("Failed to set attribute.");

      return status;
  }

  void sai_thrift_get_policer_stats(std::vector<sai_thrift_uint64_t> &_return, const sai_thrift_object_id_t thrift_policer_id,
                                    const std::vector<sai_thrift_policer_stat_t> &thrift_counter_ids) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_policer_api_t *policer_api = nullptr;
      auto status = sai_api_query(SAI_API_POLICER, reinterpret_cast<void**>(&policer_api));

      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to get API.");
          return;
      }

      auto counter_ids = reinterpret_cast<const sai_stat_id_t*>(thrift_counter_ids.data());
      sai_size_t number_of_counters = thrift_counter_ids.size();
      sai_uint64_t *counters = nullptr;

      sai_thrift_alloc_array(counters, number_of_counters);

      status = policer_api->get_policer_stats(thrift_policer_id, number_of_counters, counter_ids, counters);

      if (status == SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_DBG("Exited.");
          _return.assign(counters, counters + number_of_counters);
          sai_thrift_free_array(counters);
          return;
      }

      SAI_THRIFT_LOG_ERR("Failed to get statistics.");
      sai_thrift_free_array(counters);
  }

  sai_thrift_status_t sai_thrift_clear_policer_stats(const sai_thrift_object_id_t thrift_policer_id,
                                                     const std::vector<sai_thrift_policer_stat_t> &thrift_counter_ids) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_policer_api_t *policer_api = nullptr;
      auto status = sai_api_query(SAI_API_POLICER, reinterpret_cast<void**>(&policer_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return status; }

      auto counter_ids = reinterpret_cast<const sai_stat_id_t*>(thrift_counter_ids.data());
      sai_size_t number_of_counters = thrift_counter_ids.size();

      status = policer_api->clear_policer_stats(thrift_policer_id, number_of_counters, counter_ids);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return status; }

      SAI_THRIFT_LOG_ERR("Failed to clear statistics.");

      return status;
  }

  sai_thrift_object_id_t sai_thrift_create_scheduler_profile(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      printf("sai_thrift_create_scheduler_profile\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_scheduler_api_t *scheduler_api;
      sai_object_id_t scheduler_id = 0;
      status = sai_api_query(SAI_API_SCHEDULER, (void **) &scheduler_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parse_scheduler_attributes(thrift_attr_list, attr_list);
      uint32_t attr_count = thrift_attr_list.size();
      scheduler_api->create_scheduler(&scheduler_id, gSwitchId, attr_count, attr_list);
	  free (attr_list);
      return scheduler_id;
  }

  sai_thrift_status_t sai_thrift_remove_scheduler_profile(const sai_thrift_object_id_t scheduler_id) {
      printf("sai_thrift_remove_scheduler\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_scheduler_api_t *scheduler_api;
      status = sai_api_query(SAI_API_SCHEDULER, (void **) &scheduler_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      status = scheduler_api->remove_scheduler((sai_object_id_t) scheduler_id);
      return status;
  }

  void sai_thrift_parse_scheduler_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
              case SAI_SCHEDULER_ATTR_SCHEDULING_WEIGHT:
                  attr_list[i].value.u8 = attribute.value.u8;
                  break;
              case SAI_SCHEDULER_ATTR_MIN_BANDWIDTH_RATE:
                  attr_list[i].value.u64 = attribute.value.u64;
                  break;
              case SAI_SCHEDULER_ATTR_MIN_BANDWIDTH_BURST_RATE:
                  attr_list[i].value.u64 = attribute.value.u64;
                  break;
              case SAI_SCHEDULER_ATTR_MAX_BANDWIDTH_RATE :
                  attr_list[i].value.u64 = attribute.value.u64;
                  break;
              case SAI_SCHEDULER_ATTR_MAX_BANDWIDTH_BURST_RATE:
                  attr_list[i].value.u64 = attribute.value.u64;
                  break;
              case SAI_SCHEDULER_ATTR_SCHEDULING_TYPE:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
			  case SAI_SCHEDULER_ATTR_METER_TYPE:
			  	  attr_list[i].value.s32 = attribute.value.s32;
                  break;
          }
      }
  }

  void sai_thrift_get_scheduler_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t thrift_scheduler_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_scheduler_api_t *scheduler_api;
      uint32_t attr_count = 0;
      sai_attribute_t attr[10];
	  sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_SCHEDULER, (void **) &scheduler_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain scheduler_api, status:%d", status);
          return;
      }

      attr[0].id = SAI_SCHEDULER_ATTR_SCHEDULING_TYPE;
      attr[1].id = SAI_SCHEDULER_ATTR_SCHEDULING_WEIGHT;
	  attr[2].id = SAI_SCHEDULER_ATTR_MIN_BANDWIDTH_RATE;
	  attr[3].id = SAI_SCHEDULER_ATTR_MIN_BANDWIDTH_BURST_RATE;
      attr[4].id = SAI_SCHEDULER_ATTR_MAX_BANDWIDTH_RATE;
	  attr[5].id = SAI_SCHEDULER_ATTR_MAX_BANDWIDTH_BURST_RATE;
      attr_count = 6;

      status = scheduler_api->get_scheduler_attribute(thrift_scheduler_id, attr_count, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to get scheduler attr, status:%d", status);
          return;
      }

	  thrift_attr.id = attr[0].id;
	  thrift_attr.value.s32 = attr[0].value.s32;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[1].id;
	  thrift_attr.value.u8 = attr[1].value.u8;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[2].id;
	  thrift_attr.value.u64 = attr[2].value.u64;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[3].id;
	  thrift_attr.value.u64 = attr[3].value.u64;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[4].id;
	  thrift_attr.value.u64 = attr[4].value.u64;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[5].id;
	  thrift_attr.value.u64 = attr[5].value.u64;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
  }

  sai_thrift_status_t sai_thrift_set_scheduler_attribute(const sai_thrift_object_id_t thrift_scheduler_id, const sai_thrift_attribute_t &thrift_attr) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_scheduler_api_t *scheduler_api = nullptr;
      auto status = sai_api_query(SAI_API_SCHEDULER, reinterpret_cast<void**>(&scheduler_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return status; }

      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      sai_attribute_t *attr_list = nullptr;
      sai_size_t attr_size = thrift_attr_list.size();

      sai_thrift_alloc_array(attr_list, attr_size);
      sai_thrift_parse_scheduler_attributes(thrift_attr_list, attr_list);

      status = scheduler_api->set_scheduler_attribute(thrift_scheduler_id, attr_list);
      sai_thrift_free_array(attr_list);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return status; }

      SAI_THRIFT_LOG_ERR("Failed to set attribute.");

      return status;
  }

  sai_thrift_object_id_t sai_thrift_create_scheduler_group(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      printf("sai_thrift_create_scheduler_group\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_scheduler_group_api_t *scheduler_group_api;
      sai_object_id_t scheduler_group_id = 0;
      status = sai_api_query(SAI_API_SCHEDULER_GROUP, (void **) &scheduler_group_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parse_scheduler_group_attributes(thrift_attr_list, attr_list);
      uint32_t attr_count = thrift_attr_list.size();
      scheduler_group_api->create_scheduler_group(&scheduler_group_id, gSwitchId, attr_count, attr_list);
	  free (attr_list);
      return scheduler_group_id;
  }

  sai_thrift_status_t sai_thrift_remove_scheduler_group(const sai_thrift_object_id_t scheduler_group_id) {
      printf("sai_thrift_remove_scheduler_group\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_scheduler_group_api_t *scheduler_group_api;
      status = sai_api_query(SAI_API_SCHEDULER_GROUP, (void **) &scheduler_group_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      status = scheduler_group_api->remove_scheduler_group((sai_object_id_t) scheduler_group_id);
      return status;
  }

  void sai_thrift_parse_scheduler_group_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
              case SAI_SCHEDULER_GROUP_ATTR_PORT_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;
              case SAI_SCHEDULER_GROUP_ATTR_LEVEL:
                  attr_list[i].value.u8 = attribute.value.u8;
                  break;
              case SAI_SCHEDULER_GROUP_ATTR_MAX_CHILDS:
                  attr_list[i].value.u8 = attribute.value.u8;
                  break;
              case SAI_SCHEDULER_GROUP_ATTR_SCHEDULER_PROFILE_ID :
                  attr_list[i].value.oid = attribute.value.oid;
                  break;
              case SAI_SCHEDULER_GROUP_ATTR_PARENT_NODE:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;
          }
      }
  }

  void sai_thrift_get_scheduler_group_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t scheduler_group_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_scheduler_group_api_t *scheduler_group_api;
      uint32_t attr_count = 0;
      sai_attribute_t attr[10];
	  sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_SCHEDULER_GROUP, (void **) &scheduler_group_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain scheduler_group_api, status:%d", status);
          return;
      }

      attr[0].id = SAI_SCHEDULER_GROUP_ATTR_CHILD_COUNT;
      attr[1].id = SAI_SCHEDULER_GROUP_ATTR_CHILD_LIST;
	  attr[2].id = SAI_SCHEDULER_GROUP_ATTR_PORT_ID;
	  attr[3].id = SAI_SCHEDULER_GROUP_ATTR_LEVEL;
      attr[4].id = SAI_SCHEDULER_GROUP_ATTR_MAX_CHILDS;
	  attr[5].id = SAI_SCHEDULER_GROUP_ATTR_SCHEDULER_PROFILE_ID;
	  attr[6].id = SAI_SCHEDULER_GROUP_ATTR_PARENT_NODE;
      attr_count = 7;

	  attr[1].value.objlist.count = 64;
	  attr[1].value.objlist.list = (sai_object_id_t*)malloc(attr[1].value.objlist.count * sizeof(sai_object_id_t));

      status = scheduler_group_api->get_scheduler_group_attribute(scheduler_group_id, attr_count, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to get scheduler group attr, status:%d", status);
          return;
      }

	  thrift_attr.id = attr[0].id;
	  thrift_attr.value.u32 = attr[0].value.u32;
      thrift_attr_list.attr_list.push_back(thrift_attr);


	  thrift_attr.id = attr[1].id;
	  thrift_attr.value.objlist.count = attr[1].value.objlist.count;
	  for (int index = 0; index < attr[1].value.objlist.count; index++)
  	  {
		  thrift_attr.value.objlist.object_id_list.push_back(attr[1].value.objlist.list[index]);
  	  }
	  thrift_attr_list.attr_list.push_back(thrift_attr);

	  thrift_attr.id = attr[2].id;
	  thrift_attr.value.oid = attr[2].value.oid;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[3].id;
	  thrift_attr.value.u8 = attr[3].value.u8;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[4].id;
	  thrift_attr.value.u8 = attr[4].value.u8;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[5].id;
	  thrift_attr.value.oid = attr[5].value.oid;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
  	  thrift_attr.id = attr[6].id;
	  thrift_attr.value.oid = attr[6].value.oid;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  free(attr[1].value.objlist.list);
  }

  sai_thrift_status_t sai_thrift_set_scheduler_group_attribute(const sai_thrift_object_id_t scheduler_group_id, const sai_thrift_attribute_t &thrift_attr) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_scheduler_group_api_t *scheduler_group_api = nullptr;
      auto status = sai_api_query(SAI_API_SCHEDULER_GROUP, reinterpret_cast<void**>(&scheduler_group_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return status; }

      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      sai_attribute_t *attr_list = nullptr;
      sai_size_t attr_size = thrift_attr_list.size();

      sai_thrift_alloc_array(attr_list, attr_size);
      sai_thrift_parse_scheduler_group_attributes(thrift_attr_list, attr_list);

      status = scheduler_group_api->set_scheduler_group_attribute(scheduler_group_id, attr_list);
      sai_thrift_free_array(attr_list);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return status; }

      SAI_THRIFT_LOG_ERR("Failed to set attribute.");

      return status;
  }


  void sai_thrift_get_port_stats(std::vector<int64_t> & thrift_counters,
                                 const sai_thrift_object_id_t port_id,
                                 const std::vector<sai_thrift_port_stat_counter_t> & thrift_counter_ids,
                                 const int32_t number_of_counters) {
      printf("sai_thrift_get_port_stats\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_port_api_t *port_api;
      status = sai_api_query(SAI_API_PORT, (void **) &port_api);
      if (status != SAI_STATUS_SUCCESS) {
          return;
      }
      sai_stat_id_t *counter_ids = (sai_stat_id_t *) malloc(sizeof(sai_port_stat_t) * thrift_counter_ids.size());
      std::vector<int32_t>::const_iterator it = thrift_counter_ids.begin();
      uint64_t *counters = (uint64_t *) malloc(sizeof(uint64_t) * thrift_counter_ids.size());
      for(uint32_t i = 0; i < thrift_counter_ids.size(); i++, it++) {
          counter_ids[i] = (sai_port_stat_t) *it;
      }

      status = port_api->get_port_stats((sai_object_id_t) port_id,
                                        number_of_counters,
                                        counter_ids,
                                        counters);

      for (uint32_t i = 0; i < thrift_counter_ids.size(); i++) {
          thrift_counters.push_back(counters[i]);
      }
      free(counter_ids);
      free(counters);
      return;
  }

  sai_thrift_status_t sai_thrift_clear_port_all_stats(const sai_thrift_object_id_t port_id) {
      printf("sai_thrift_clear_port_all_stats\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_port_api_t *port_api;
      status = sai_api_query(SAI_API_PORT, (void **) &port_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      status = port_api->clear_port_all_stats( (sai_object_id_t) port_id);
      return status;
  }

  void sai_thrift_get_port_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t port_id) {
      printf("sai_thrift_get_port_attribute\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_port_api_t *port_api;
      sai_attribute_t max_queue_attribute;
      sai_attribute_t queue_list_object_attribute;
      sai_thrift_attribute_t thrift_queue_list_attribute;
      sai_object_list_t *queue_list_object;
      int max_queues = 0;
	  std::vector<sai_thrift_attribute_t>& attr_list = thrift_attr_list.attr_list;
	  sai_attribute_t attr_temp;
	  sai_thrift_attribute_t thrift_attr_temp;

	  memset(&attr_temp, 0, sizeof(attr_temp));
      status = sai_api_query(SAI_API_PORT, (void **) &port_api);
      if (status != SAI_STATUS_SUCCESS) {
          return;
      }
	  thrift_attr_list.attr_count = 0;

      max_queue_attribute.id = SAI_PORT_ATTR_QOS_NUMBER_OF_QUEUES;
      port_api->get_port_attribute(port_id, 1, &max_queue_attribute);
      thrift_queue_list_attribute.id = SAI_PORT_ATTR_QOS_NUMBER_OF_QUEUES;
      thrift_queue_list_attribute.value.u32 = max_queue_attribute.value.u32;
      attr_list.push_back(thrift_queue_list_attribute);

      max_queues = max_queue_attribute.value.u32;
      queue_list_object_attribute.id = SAI_PORT_ATTR_QOS_QUEUE_LIST;
      queue_list_object_attribute.value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * max_queues);
      queue_list_object_attribute.value.objlist.count = max_queues;
      port_api->get_port_attribute(port_id, 1, &queue_list_object_attribute);



      thrift_queue_list_attribute.id = SAI_PORT_ATTR_QOS_QUEUE_LIST;
      thrift_queue_list_attribute.value.objlist.count = max_queues;
      std::vector<sai_thrift_object_id_t>& queue_list = thrift_queue_list_attribute.value.objlist.object_id_list;
      queue_list_object = &queue_list_object_attribute.value.objlist;
      for (int index = 0; index < max_queues; index++) {
          queue_list.push_back((sai_thrift_object_id_t) queue_list_object->list[index]);
      }
      attr_list.push_back(thrift_queue_list_attribute);
      free(queue_list_object_attribute.value.objlist.list);


      attr_temp.id = SAI_PORT_ATTR_QOS_SCHEDULER_PROFILE_ID;
      port_api->get_port_attribute(port_id, 1, &attr_temp);
      thrift_attr_temp.id = SAI_PORT_ATTR_QOS_SCHEDULER_PROFILE_ID;
      thrift_attr_temp.value.oid = attr_temp.value.oid;
      attr_list.push_back(thrift_attr_temp);

      sai_uint32_t sched_group_num = 0;
      attr_temp.id = SAI_PORT_ATTR_QOS_NUMBER_OF_SCHEDULER_GROUPS;
      port_api->get_port_attribute(port_id, 1, &attr_temp);
      thrift_attr_temp.id = SAI_PORT_ATTR_QOS_NUMBER_OF_SCHEDULER_GROUPS;
      thrift_attr_temp.value.u32 = attr_temp.value.u32;
      sched_group_num = attr_temp.value.u32;
      attr_list.push_back(thrift_attr_temp);
      attr_temp.id = SAI_PORT_ATTR_QOS_SCHEDULER_GROUP_LIST;
      attr_temp.value.objlist.count = sched_group_num;
      attr_temp.value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * sched_group_num);
      port_api->get_port_attribute(port_id, 1, &attr_temp);
      std :: vector < sai_thrift_object_id_t > & object_list = thrift_attr_temp.value.objlist.object_id_list;
      for (int index = 0; index < sched_group_num; index++)
      {
          object_list.push_back((sai_thrift_object_id_t) attr_temp.value.objlist.list[index]);
      }
      thrift_attr_temp.id = SAI_PORT_ATTR_QOS_SCHEDULER_GROUP_LIST;
      thrift_attr_temp.value.objlist.count = attr_temp.value.objlist.count;
      attr_list.push_back(thrift_attr_temp);
      free(attr_temp.value.objlist.list);

      sai_uint32_t ingress_pg_num = 0;
      attr_temp.id = SAI_PORT_ATTR_NUMBER_OF_INGRESS_PRIORITY_GROUPS;
      port_api->get_port_attribute(port_id, 1, &attr_temp);
      thrift_attr_temp.id = SAI_PORT_ATTR_NUMBER_OF_INGRESS_PRIORITY_GROUPS;
      thrift_attr_temp.value.u32 = attr_temp.value.u32;
      ingress_pg_num = attr_temp.value.u32;
      attr_list.push_back(thrift_attr_temp);
      attr_temp.id = SAI_PORT_ATTR_INGRESS_PRIORITY_GROUP_LIST;
      attr_temp.value.objlist.count = ingress_pg_num;
      attr_temp.value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * ingress_pg_num);
      port_api->get_port_attribute(port_id, 1, &attr_temp);
      object_list = thrift_attr_temp.value.objlist.object_id_list;
      for (int index = 0; index < ingress_pg_num; index++)
      {
          object_list.push_back((sai_thrift_object_id_t) attr_temp.value.objlist.list[index]);
      }
      thrift_attr_temp.id = SAI_PORT_ATTR_INGRESS_PRIORITY_GROUP_LIST;
      thrift_attr_temp.value.objlist.count = attr_temp.value.objlist.count;
      attr_list.push_back(thrift_attr_temp);
      free(attr_temp.value.objlist.list);

      attr_temp.id = SAI_PORT_ATTR_PRIORITY_FLOW_CONTROL;
      port_api->get_port_attribute(port_id, 1, &attr_temp);
      thrift_attr_temp.id = SAI_PORT_ATTR_PRIORITY_FLOW_CONTROL;
      thrift_attr_temp.value.u8 = attr_temp.value.u8;
      attr_list.push_back(thrift_attr_temp);

      attr_temp.id = SAI_PORT_ATTR_EGRESS_BLOCK_PORT_LIST;
      attr_temp.value.objlist.count = 40;
      attr_temp.value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * 40);
      port_api->get_port_attribute(port_id, 1, &attr_temp);
      object_list = thrift_attr_temp.value.objlist.object_id_list;
      for (int index = 0; index < 40; index++)
      {
          object_list.push_back((sai_thrift_object_id_t) attr_temp.value.objlist.list[index]);
      }
	  thrift_attr_temp.id = SAI_PORT_ATTR_EGRESS_BLOCK_PORT_LIST;
      thrift_attr_temp.value.objlist.count = attr_temp.value.objlist.count;
      attr_list.push_back(thrift_attr_temp);
	  free(attr_temp.value.objlist.list);
#if 0
      sai_attribute_t max_pg_attribute;
      sai_attribute_t pg_list_object_attribute;
      sai_thrift_attribute_t thrift_pg_list_attribute;
      sai_object_list_t *pg_list_object;
      int max_pg = 0;

      max_pg_attribute.id = SAI_PORT_ATTR_NUMBER_OF_INGRESS_PRIORITY_GROUPS;
      port_api->get_port_attribute(port_id, 1, &max_pg_attribute);
      max_pg = max_pg_attribute.value.u32;
      pg_list_object_attribute.id = SAI_PORT_ATTR_INGRESS_PRIORITY_GROUP_LIST;
      pg_list_object_attribute.value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * max_pg);
      pg_list_object_attribute.value.objlist.count = max_pg;
      port_api->get_port_attribute(port_id, 1, &pg_list_object_attribute);

      thrift_attr_list.attr_count = 3;
      thrift_pg_list_attribute.id = SAI_PORT_ATTR_INGRESS_PRIORITY_GROUP_LIST;
      thrift_pg_list_attribute.value.objlist.count = max_pg;
      std::vector<sai_thrift_object_id_t>& pg_list = thrift_pg_list_attribute.value.objlist.object_id_list;
      pg_list_object = &pg_list_object_attribute.value.objlist;
      for (int index = 0; index < max_pg; index++) {
          pg_list.push_back((sai_thrift_object_id_t) pg_list_object->list[index]);
      }
      attr_list.push_back(thrift_pg_list_attribute);
      free(pg_list_object_attribute.value.objlist.list);
      std::vector<sai_thrift_attribute_t>& attr_list = thrift_attr_list.attr_list;
#endif
      sai_attribute_t port_hw_lane;
      sai_thrift_attribute_t thrift_port_hw_lane;
      sai_u32_list_t *lane_list_num;

      port_hw_lane.id = SAI_PORT_ATTR_HW_LANE_LIST;
      port_hw_lane.value.u32list.list = (uint32_t *) malloc(sizeof(uint32_t) * 4);
      port_hw_lane.value.u32list.count = 1;
      port_api->get_port_attribute(port_id, 1, &port_hw_lane);

      thrift_attr_list.attr_count = 4;
      thrift_port_hw_lane.id = SAI_PORT_ATTR_HW_LANE_LIST;
      thrift_port_hw_lane.value.u32list.count = port_hw_lane.value.u32list.count;
      std::vector<int32_t>& lane_list = thrift_port_hw_lane.value.u32list.u32list;
      lane_list_num = &port_hw_lane.value.u32list;
      for (int index = 0; index < port_hw_lane.value.u32list.count ; index++) {
          lane_list.push_back((uint32_t) lane_list_num->list[index]);
      }
      attr_list.push_back(thrift_port_hw_lane);
      free(port_hw_lane.value.u32list.list);

      sai_attribute_t port_oper_status_attribute;
      sai_thrift_attribute_t thrift_port_status;
      port_oper_status_attribute.id = SAI_PORT_ATTR_OPER_STATUS;
      port_api->get_port_attribute(port_id, 1, &port_oper_status_attribute);

      thrift_attr_list.attr_count = 2;
      thrift_port_status.id = SAI_PORT_ATTR_OPER_STATUS;
      thrift_port_status.value.s32 =  port_oper_status_attribute.value.s32;
      attr_list.push_back(thrift_port_status);


      sai_attribute_t port_mtu_attribute;
      sai_thrift_attribute_t thrift_mtu_status;
      port_mtu_attribute.id = SAI_PORT_ATTR_MTU;
      port_api->get_port_attribute(port_id, 1, &port_mtu_attribute);

      thrift_mtu_status.id = SAI_PORT_ATTR_MTU;
      thrift_mtu_status.value.u32 =  port_mtu_attribute.value.u32;
      attr_list.push_back(thrift_mtu_status);

	  sai_attribute_t port_tx_enable;
      sai_thrift_attribute_t thrift_port_tx_enable;
      port_tx_enable.id = SAI_PORT_ATTR_PKT_TX_ENABLE;
      port_api->get_port_attribute(port_id, 1, &port_tx_enable);

      thrift_port_tx_enable.id = SAI_PORT_ATTR_PKT_TX_ENABLE;
      thrift_port_tx_enable.value.booldata =  port_tx_enable.value.booldata;
      attr_list.push_back(thrift_port_tx_enable);
  }

  void sai_thrift_get_queue_stats(std::vector<int64_t> & thrift_counters,
                                  const sai_thrift_object_id_t queue_id,
                                  const std::vector<sai_thrift_queue_stat_counter_t> & thrift_counter_ids,
                                  const int32_t number_of_counters) {
      printf("sai_thrift_get_queue_stats\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_queue_api_t *queue_api;
      status = sai_api_query(SAI_API_QUEUE, (void **) &queue_api);
      if (status != SAI_STATUS_SUCCESS) {
          return;
      }
      sai_stat_id_t *counter_ids = (sai_stat_id_t *) malloc(sizeof(sai_queue_stat_t) * thrift_counter_ids.size());
      std::vector<int32_t>::const_iterator it = thrift_counter_ids.begin();
      uint64_t *counters = (uint64_t *) malloc(sizeof(uint64_t) * thrift_counter_ids.size());
      for(uint32_t i = 0; i < thrift_counter_ids.size(); i++, it++) {
          counter_ids[i] = (sai_queue_stat_t) *it;
      }

      status = queue_api->get_queue_stats(
                             (sai_object_id_t) queue_id,
                             number_of_counters,
                             counter_ids,
                             counters);

      for (uint32_t i = 0; i < thrift_counter_ids.size(); i++) {
          thrift_counters.push_back(counters[i]);
      }
      free(counter_ids);
      free(counters);
      return;
   }

  void sai_thrift_parse_queue_attributes(sai_attribute_t *attr_list,
                                           const std::vector<sai_thrift_attribute_t> &thrift_attr_list) const noexcept
  {
      if (attr_list == nullptr || thrift_attr_list.empty())
      { SAI_THRIFT_LOG_ERR("Invalid input arguments."); return; }

      std::vector<sai_thrift_attribute_t>::const_iterator cit = thrift_attr_list.begin();

      for (sai_size_t i = 0; i < thrift_attr_list.size(); i++, cit++)
      {
          sai_thrift_attribute_t attribute = *cit;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
              case SAI_QUEUE_ATTR_TYPE:
                  attr_list[i].value.u32 = attribute.value.u32;
                  break;
			  case SAI_QUEUE_ATTR_INDEX:
			  	  attr_list[i].value.u8 = attribute.value.u8;
                  break;
			  case SAI_QUEUE_ATTR_PORT:
			  case SAI_QUEUE_ATTR_PARENT_SCHEDULER_NODE:
			  case SAI_QUEUE_ATTR_WRED_PROFILE_ID:
			  case SAI_QUEUE_ATTR_SCHEDULER_PROFILE_ID:
			  	  attr_list[i].value.oid = attribute.value.oid;
                  break;
              default:
                  SAI_THRIFT_LOG_ERR("Failed to parse attribute.");
                  break;
          }
      }
  }
  sai_thrift_object_id_t sai_thrift_create_queue(const std::vector<sai_thrift_attribute_t> &thrift_attr_list) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_queue_api_t *queue_api = nullptr;
      auto status = sai_api_query(SAI_API_QUEUE, reinterpret_cast<void**>(&queue_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return SAI_NULL_OBJECT_ID; }

      sai_attribute_t *attr_list = nullptr;
      sai_size_t attr_size = thrift_attr_list.size();

      sai_thrift_alloc_array(attr_list, attr_size);
      sai_thrift_parse_queue_attributes(attr_list, thrift_attr_list);

      sai_object_id_t queue_oid = 0;
      status = queue_api->create_queue(&queue_oid, gSwitchId, attr_size, attr_list);
      sai_thrift_free_array(attr_list);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return queue_oid; }

      SAI_THRIFT_LOG_ERR("Failed to create OID.");

      return SAI_NULL_OBJECT_ID;
  }

  sai_thrift_status_t sai_thrift_remove_queue(const sai_thrift_object_id_t queue_id) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_queue_api_t *queue_api = nullptr;
      auto status = sai_api_query(SAI_API_QUEUE, reinterpret_cast<void**>(&queue_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return status; }

      status = queue_api->remove_queue(queue_id);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return status; }

      SAI_THRIFT_LOG_ERR("Failed to remove OID.");

      return status;
  }

    void sai_thrift_get_queue_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t queue_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_queue_api_t *queue_api;
      uint32_t attr_count = 0;
      sai_attribute_t attr[10];
	  sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_QUEUE, (void **) &queue_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain queue_api, status:%d", status);
          return;
      }

      attr[0].id = SAI_QUEUE_ATTR_TYPE;
      attr[1].id = SAI_QUEUE_ATTR_PORT;
	  attr[2].id = SAI_QUEUE_ATTR_INDEX;
	  attr[3].id = SAI_QUEUE_ATTR_PARENT_SCHEDULER_NODE;
      attr[4].id = SAI_QUEUE_ATTR_WRED_PROFILE_ID;
	  attr[5].id = SAI_QUEUE_ATTR_SCHEDULER_PROFILE_ID;
	  attr[6].id = SAI_QUEUE_ATTR_BUFFER_PROFILE_ID;
      attr_count = 7;

      status = queue_api->get_queue_attribute(queue_id, attr_count, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to get queue attr, status:%d", status);
          return;
      }

	  thrift_attr.id = attr[0].id;
	  thrift_attr.value.u32 = attr[0].value.u32;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[1].id;
	  thrift_attr.value.oid = attr[1].value.oid;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[2].id;
	  thrift_attr.value.u8 = attr[2].value.u8;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[3].id;
	  thrift_attr.value.oid = attr[3].value.oid;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[4].id;
	  thrift_attr.value.oid = attr[4].value.oid;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[5].id;
	  thrift_attr.value.oid = attr[5].value.oid;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[6].id;
	  thrift_attr.value.oid = attr[6].value.oid;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
  }


  sai_thrift_status_t sai_thrift_set_queue_attribute(const sai_thrift_object_id_t queue_id,
                                                     const sai_thrift_attribute_t& thrift_attr) {
      printf("sai_thrift_set_queue_attribute\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_queue_api_t *queue_api;
      status = sai_api_query(SAI_API_QUEUE, (void **) &queue_api);
        if (status != SAI_STATUS_SUCCESS) {
            return status;
        }
      sai_attribute_t attr;
      attr.id = thrift_attr.id;
      attr.value.oid = thrift_attr.value.oid;
      status = queue_api->set_queue_attribute((sai_object_id_t)queue_id, &attr);
      return status;
  }

  sai_thrift_status_t sai_thrift_clear_queue_stats(const sai_thrift_object_id_t queue_id,
                                                   const std::vector<sai_thrift_queue_stat_counter_t> & thrift_counter_ids,
                                                   const int32_t number_of_counters) {
      printf("sai_thrift_clear_queue_stats\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_queue_api_t *queue_api;
      status = sai_api_query(SAI_API_QUEUE, (void **) &queue_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_stat_id_t *counter_ids = (sai_stat_id_t *) malloc(sizeof(sai_queue_stat_t) * thrift_counter_ids.size());
      std::vector<int32_t>::const_iterator it = thrift_counter_ids.begin();
      for(uint32_t i = 0; i < thrift_counter_ids.size(); i++, it++) {
          counter_ids[i] = (sai_queue_stat_t) *it;
      }

      status = queue_api->clear_queue_stats(
                             (sai_object_id_t) queue_id,
                             number_of_counters,
                             counter_ids);

      free(counter_ids);
      return status;
  }

  sai_thrift_object_id_t sai_thrift_create_buffer_profile(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
    printf("sai_thrift_create_buffer_profile\n");
    sai_status_t status = SAI_STATUS_SUCCESS;
    sai_buffer_api_t *buffer_api;
    sai_object_id_t buffer_id = 0;
    status = sai_api_query(SAI_API_BUFFER, (void **) &buffer_api);
    if (status != SAI_STATUS_SUCCESS) {
        return status;
    }
    sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
    sai_thrift_parse_buffer_attributes(thrift_attr_list, attr_list);
    uint32_t attr_count = thrift_attr_list.size();
    buffer_api->create_buffer_profile(&buffer_id, gSwitchId, attr_count, attr_list);

    return buffer_id;
  }

  void sai_thrift_parse_buffer_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
    std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
    sai_thrift_attribute_t attribute;
    for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
        attribute = (sai_thrift_attribute_t)*it;
        attr_list[i].id = attribute.id;
        switch (attribute.id) {
            case SAI_BUFFER_PROFILE_ATTR_POOL_ID:
                attr_list[i].value.oid = attribute.value.oid;
                break;
            case SAI_BUFFER_PROFILE_ATTR_BUFFER_SIZE:
                attr_list[i].value.u32 = attribute.value.u32;
                break;
            case SAI_BUFFER_PROFILE_ATTR_THRESHOLD_MODE:
                attr_list[i].value.s32 = attribute.value.s32;
                break;
            case SAI_BUFFER_PROFILE_ATTR_SHARED_DYNAMIC_TH:
                attr_list[i].value.s8 = attribute.value.s8;
                break;
            case SAI_BUFFER_PROFILE_ATTR_SHARED_STATIC_TH:
                attr_list[i].value.u32 = attribute.value.u32;
                break;
            case SAI_BUFFER_PROFILE_ATTR_XOFF_TH:
                attr_list[i].value.u32 = attribute.value.u32;
                break;
            case SAI_BUFFER_PROFILE_ATTR_XON_TH:
                attr_list[i].value.u32 = attribute.value.u32;
                break;
        }
    }
  }

  sai_thrift_status_t sai_thrift_remove_buffer_profile(const sai_thrift_object_id_t buffer_profile_id) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_buffer_api_t *buffer_api = nullptr;
      auto status = sai_api_query(SAI_API_BUFFER, reinterpret_cast<void**>(&buffer_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return status; }

      status = buffer_api->remove_buffer_profile(buffer_profile_id);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return status; }

      SAI_THRIFT_LOG_ERR("Failed to remove OID.");

      return status;
  }

  void sai_thrift_get_buffer_profile_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t buffer_profile_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_buffer_api_t *buffer_api;
      uint32_t attr_count = 0;
      sai_attribute_t attr[10];
	  sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_BUFFER, (void **) &buffer_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain buffer api, status:%d", status);
          return;
      }

      attr[0].id = SAI_BUFFER_PROFILE_ATTR_POOL_ID;
      attr[1].id = SAI_BUFFER_PROFILE_ATTR_BUFFER_SIZE;
	  attr[2].id = SAI_BUFFER_PROFILE_ATTR_THRESHOLD_MODE;
	  attr[3].id = SAI_BUFFER_PROFILE_ATTR_SHARED_DYNAMIC_TH;
      attr[4].id = SAI_BUFFER_PROFILE_ATTR_SHARED_STATIC_TH;
	  attr[5].id = SAI_BUFFER_PROFILE_ATTR_XOFF_TH;
	  attr[6].id = SAI_BUFFER_PROFILE_ATTR_XON_TH;
      attr_count = 7;

      status = buffer_api->get_buffer_profile_attribute(buffer_profile_id, attr_count, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to get buffer profile attr, status:%d", status);
          return;
      }

	  thrift_attr.id = attr[0].id;
	  thrift_attr.value.oid = attr[0].value.oid;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[1].id;
	  thrift_attr.value.u32 = attr[1].value.u32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[2].id;
	  thrift_attr.value.s32 = attr[2].value.s32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[3].id;
	  thrift_attr.value.s8 = attr[3].value.s8;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[4].id;
	  thrift_attr.value.u32 = attr[4].value.u32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[5].id;
	  thrift_attr.value.u32 = attr[5].value.u32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[6].id;
	  thrift_attr.value.u32 = attr[6].value.u32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
  }

  sai_thrift_status_t sai_thrift_set_buffer_profile_attribute(const sai_thrift_object_id_t buffer_profile_id, const sai_thrift_attribute_t &thrift_attr) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_buffer_api_t *buffer_api = nullptr;
      auto status = sai_api_query(SAI_API_BUFFER, reinterpret_cast<void**>(&buffer_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return status; }

      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      sai_attribute_t *attr_list = nullptr;
      sai_size_t attr_size = thrift_attr_list.size();

      sai_thrift_alloc_array(attr_list, attr_size);
      sai_thrift_parse_buffer_attributes(thrift_attr_list, attr_list);

      status = buffer_api->set_buffer_profile_attribute(buffer_profile_id, attr_list);
      sai_thrift_free_array(attr_list);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return status; }

      SAI_THRIFT_LOG_ERR("Failed to set attribute.");

      return status;
  }

  sai_thrift_object_id_t sai_thrift_create_pool_profile(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
    printf("sai_thrift_create_pool\n");
    sai_status_t status = SAI_STATUS_SUCCESS;
    sai_buffer_api_t *buffer_api;
    sai_object_id_t pool_id = 0;
    status = sai_api_query(SAI_API_BUFFER, (void **) &buffer_api);
    if (status != SAI_STATUS_SUCCESS) {
        return status;
    }
    sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
    sai_thrift_parse_pool_attributes(thrift_attr_list, attr_list);
    uint32_t attr_count = thrift_attr_list.size();
    buffer_api->create_buffer_pool(&pool_id, gSwitchId, attr_count, attr_list);
    return pool_id;
  }

  void sai_thrift_parse_pool_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
    std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
    sai_thrift_attribute_t attribute;
    for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
        attribute = (sai_thrift_attribute_t)*it;
        attr_list[i].id = attribute.id;
        switch (attribute.id) {
            case SAI_BUFFER_POOL_ATTR_TYPE:
                attr_list[i].value.u32 = attribute.value.s32;
                break;
            case SAI_BUFFER_POOL_ATTR_SIZE:
                attr_list[i].value.u32 = attribute.value.u32;
                break;
            case SAI_BUFFER_POOL_ATTR_THRESHOLD_MODE:
                attr_list[i].value.u32 = attribute.value.s32;
                break;
        }
    }
  }

  void sai_thrift_parse_priority_group_attributes(sai_attribute_t *attr_list,
                                           const std::vector<sai_thrift_attribute_t> &thrift_attr_list) const noexcept
  {
      if (attr_list == nullptr || thrift_attr_list.empty())
      { SAI_THRIFT_LOG_ERR("Invalid input arguments."); return; }

      std::vector<sai_thrift_attribute_t>::const_iterator cit = thrift_attr_list.begin();

      for (sai_size_t i = 0; i < thrift_attr_list.size(); i++, cit++)
      {
          sai_thrift_attribute_t attribute = *cit;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
			  case SAI_INGRESS_PRIORITY_GROUP_ATTR_INDEX:
			  	  attr_list[i].value.u8 = attribute.value.u8;
                  break;
			  case SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE:
			  case SAI_INGRESS_PRIORITY_GROUP_ATTR_PORT:
			  	  attr_list[i].value.oid = attribute.value.oid;
                  break;
              default:
                  SAI_THRIFT_LOG_ERR("Failed to parse attribute.");
                  break;
          }
      }
  }
  sai_thrift_object_id_t sai_thrift_create_priority_group(const std::vector<sai_thrift_attribute_t> &thrift_attr_list) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_buffer_api_t *buffer_api = nullptr;
      auto status = sai_api_query(SAI_API_BUFFER, reinterpret_cast<void**>(&buffer_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return SAI_NULL_OBJECT_ID; }

      sai_attribute_t *attr_list = nullptr;
      sai_size_t attr_size = thrift_attr_list.size();

      sai_thrift_alloc_array(attr_list, attr_size);
      sai_thrift_parse_priority_group_attributes(attr_list, thrift_attr_list);

      sai_object_id_t priority_group_oid = 0;
      status = buffer_api->create_ingress_priority_group(&priority_group_oid, gSwitchId, attr_size, attr_list);
      sai_thrift_free_array(attr_list);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return priority_group_oid; }

      SAI_THRIFT_LOG_ERR("Failed to create OID.");

      return SAI_NULL_OBJECT_ID;
  }

  sai_thrift_status_t sai_thrift_remove_priority_group(const sai_thrift_object_id_t priority_group_oid) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_buffer_api_t *buffer_api = nullptr;
      auto status = sai_api_query(SAI_API_BUFFER, reinterpret_cast<void**>(&buffer_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return status; }

      status = buffer_api->remove_ingress_priority_group(priority_group_oid);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return status; }

      SAI_THRIFT_LOG_ERR("Failed to remove OID.");

      return status;
  }


  void sai_thrift_get_priority_group_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t priority_group_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_buffer_api_t *buffer_api;
      uint32_t attr_count = 0;
      sai_attribute_t attr[10];
	  sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_BUFFER, (void **) &buffer_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain buffer api, status:%d", status);
          return;
      }

      attr[0].id = SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE;
      attr[1].id = SAI_INGRESS_PRIORITY_GROUP_ATTR_PORT;
	  attr[2].id = SAI_INGRESS_PRIORITY_GROUP_ATTR_INDEX;
      attr_count = 3;

      status = buffer_api->get_ingress_priority_group_attribute(priority_group_id, attr_count, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to get ingress priority group attr, status:%d", status);
          return;
      }

	  thrift_attr.id = attr[0].id;
	  thrift_attr.value.oid = attr[0].value.oid;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[1].id;
	  thrift_attr.value.oid = attr[1].value.oid;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[2].id;
	  thrift_attr.value.u8 = attr[2].value.u8;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
  }

  sai_thrift_status_t sai_thrift_set_priority_group_attribute(const sai_thrift_object_id_t pg_id, const sai_thrift_attribute_t& thrift_attr) {
      printf("sai_thrift_set_priority_group_attribute\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_buffer_api_t *buffer_api;
      status = sai_api_query(SAI_API_BUFFER, (void **) &buffer_api);
        if (status != SAI_STATUS_SUCCESS) {
            return status;
        }
      sai_attribute_t attr;
      attr.id = thrift_attr.id;
      attr.value.oid = thrift_attr.value.oid;
      status = buffer_api->set_ingress_priority_group_attribute((sai_object_id_t)pg_id, &attr);
      return status;
  }

  void sai_thrift_get_pg_stats(std::vector<int64_t> & thrift_counters,
                               const sai_thrift_object_id_t pg_id,
                               const std::vector<sai_thrift_pg_stat_counter_t> & thrift_counter_ids,
                               const int32_t number_of_counters) {
      printf("sai_thrift_get_pg_stats\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_buffer_api_t *buffer_api;
      status = sai_api_query(SAI_API_BUFFER, (void **) &buffer_api);
      if (status != SAI_STATUS_SUCCESS) {
          return;
      }
      sai_stat_id_t *counter_ids = (sai_stat_id_t *) malloc(sizeof(sai_ingress_priority_group_stat_t) * thrift_counter_ids.size());
      std::vector<int32_t>::const_iterator it = thrift_counter_ids.begin();
      uint64_t *counters = (uint64_t *) malloc(sizeof(uint64_t) * thrift_counter_ids.size());
      for(uint32_t i = 0; i < thrift_counter_ids.size(); i++, it++) {
          counter_ids[i] = (sai_ingress_priority_group_stat_t) *it;
      }

      status = buffer_api->get_ingress_priority_group_stats((sai_object_id_t) pg_id,
                                                            number_of_counters,
                                                            counter_ids,
                                                            counters);

      for (uint32_t i = 0; i < thrift_counter_ids.size(); i++) {
          thrift_counters.push_back(counters[i]);
      }
      free(counter_ids);
      free(counters);
      return;
   }

  sai_thrift_object_id_t sai_thrift_create_wred_profile(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      printf("sai_thrift_create_wred_profile\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_wred_api_t *wred_api;
      sai_object_id_t wred_id = 0;
      status = sai_api_query(SAI_API_WRED, (void **) &wred_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());
      sai_thrift_parse_wred_attributes(thrift_attr_list, attr_list);
      uint32_t attr_count = thrift_attr_list.size();
      wred_api->create_wred(&wred_id, gSwitchId, attr_count, attr_list);
      free(attr_list);
      return wred_id;
  }

  void sai_thrift_parse_wred_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;
          switch (attribute.id) {
              case SAI_WRED_ATTR_GREEN_ENABLE:
                  attr_list[i].value.booldata = attribute.value.booldata;
                  break;
              case SAI_WRED_ATTR_GREEN_MIN_THRESHOLD:
                  attr_list[i].value.u32 = attribute.value.u32;
                  break;
              case SAI_WRED_ATTR_GREEN_MAX_THRESHOLD:
                  attr_list[i].value.u32 = attribute.value.u32;
                  break;
              case SAI_WRED_ATTR_GREEN_DROP_PROBABILITY:
                  attr_list[i].value.u32 = attribute.value.u32;
                  break;
              case SAI_WRED_ATTR_YELLOW_ENABLE:
                  attr_list[i].value.booldata = attribute.value.booldata;
                  break;
              case SAI_WRED_ATTR_YELLOW_MIN_THRESHOLD:
                  attr_list[i].value.u32 = attribute.value.u32;
                  break;
              case SAI_WRED_ATTR_YELLOW_MAX_THRESHOLD:
                  attr_list[i].value.u32 = attribute.value.u32;
                  break;
              case SAI_WRED_ATTR_YELLOW_DROP_PROBABILITY:
                  attr_list[i].value.u32 = attribute.value.u32;
                  break;
              case SAI_WRED_ATTR_RED_ENABLE:
                  attr_list[i].value.booldata = attribute.value.booldata;
                  break;
              case SAI_WRED_ATTR_RED_MIN_THRESHOLD:
                  attr_list[i].value.u32 = attribute.value.u32;
                  break;
              case SAI_WRED_ATTR_RED_MAX_THRESHOLD:
                  attr_list[i].value.u32 = attribute.value.u32;
                  break;
              case SAI_WRED_ATTR_RED_DROP_PROBABILITY:
                  attr_list[i].value.u32 = attribute.value.u32;
                  break;
              case SAI_WRED_ATTR_WEIGHT:
                  attr_list[i].value.u8 = attribute.value.u8;
                  break;
              case SAI_WRED_ATTR_ECN_MARK_MODE:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;
          }
      }
  }

  sai_thrift_status_t sai_thrift_remove_wred_profile(const sai_thrift_object_id_t wred_id) {
      printf("sai_thrift_remove_wred_profile\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_wred_api_t *wred_api;
      status = sai_api_query(SAI_API_WRED, (void **) &wred_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      status = wred_api->remove_wred((sai_object_id_t) wred_id);
      return status;
  }

  void sai_thrift_get_wred_attribute_profile(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t wred_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_wred_api_t *wred_api;
      uint32_t attr_count = 0;
      sai_attribute_t attr[12];
	  sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_WRED, (void **) &wred_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain wred_api, status:%d", status);
          return;
      }

      attr[0].id = SAI_WRED_ATTR_GREEN_ENABLE;
      attr[1].id = SAI_WRED_ATTR_GREEN_MIN_THRESHOLD;
	  attr[2].id = SAI_WRED_ATTR_GREEN_MAX_THRESHOLD;
	  attr[3].id = SAI_WRED_ATTR_GREEN_DROP_PROBABILITY;
      attr[4].id = SAI_WRED_ATTR_YELLOW_ENABLE;
	  attr[5].id = SAI_WRED_ATTR_YELLOW_MIN_THRESHOLD;
	  attr[6].id = SAI_WRED_ATTR_YELLOW_MAX_THRESHOLD;
      attr[7].id = SAI_WRED_ATTR_YELLOW_DROP_PROBABILITY;
	  attr[8].id = SAI_WRED_ATTR_RED_ENABLE;
	  attr[9].id = SAI_WRED_ATTR_RED_MIN_THRESHOLD;
	  attr[10].id = SAI_WRED_ATTR_RED_MAX_THRESHOLD;
      attr[11].id = SAI_WRED_ATTR_RED_DROP_PROBABILITY;
      attr_count = 12;

      status = wred_api->get_wred_attribute(wred_id, attr_count, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to get wred attr, status:%d", status);
          return;
      }

	  thrift_attr.id = attr[0].id;
	  thrift_attr.value.booldata = attr[0].value.booldata;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[1].id;
	  thrift_attr.value.u32 = attr[1].value.u32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[2].id;
	  thrift_attr.value.u32 = attr[2].value.u32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[3].id;
	  thrift_attr.value.u32 = attr[3].value.u32;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[4].id;
	  thrift_attr.value.booldata = attr[4].value.booldata;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[5].id;
	  thrift_attr.value.u32 = attr[5].value.u32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[6].id;
	  thrift_attr.value.u32 = attr[6].value.u32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
  	  thrift_attr.id = attr[7].id;
	  thrift_attr.value.u32 = attr[7].value.u32;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[8].id;
	  thrift_attr.value.booldata = attr[8].value.booldata;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[9].id;
	  thrift_attr.value.u32 = attr[9].value.u32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[10].id;
	  thrift_attr.value.u32 = attr[10].value.u32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[11].id;
	  thrift_attr.value.u32 = attr[11].value.u32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);

  }

  sai_thrift_status_t sai_thrift_set_wred_attribute_profile(const sai_thrift_object_id_t wred_id, const sai_thrift_attribute_t &thrift_attr)
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_wred_api_t *wred_api = nullptr;
      auto status = sai_api_query(SAI_API_WRED, reinterpret_cast<void**>(&wred_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return status; }

      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      sai_attribute_t *attr_list = nullptr;
      sai_size_t attr_size = thrift_attr_list.size();

      sai_thrift_alloc_array(attr_list, attr_size);
      sai_thrift_parse_wred_attributes(thrift_attr_list, attr_list);

      status = wred_api->set_wred_attribute(wred_id, attr_list);
      sai_thrift_free_array(attr_list);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return status; }

      SAI_THRIFT_LOG_ERR("Failed to set attribute.");

      return status;
  }

  sai_thrift_object_id_t sai_thrift_create_qos_map(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      sai_attribute_t *attr_list;
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_qos_map_api_t *qos_map_api;
      sai_object_id_t qos_map_id = 0;
      sai_qos_map_t *qos_map_list = NULL;

      printf("sai_thrift_create_qos_map\n");

      status = sai_api_query(SAI_API_QOS_MAP, (void **) &qos_map_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }

      attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_list.size());

      for (uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;

          switch (attribute.id) {
              case SAI_QOS_MAP_ATTR_TYPE:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;

              case SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST:
                  sai_attribute_t *attr = &attr_list[i];

                  attr->value.qosmap.count = attribute.value.qosmap.count;

                  qos_map_list = (sai_qos_map_t *) malloc(attr->value.qosmap.count * sizeof(sai_qos_map_t));
                  attr->value.qosmap.list = qos_map_list;

                  for (uint32_t j = 0; j < attribute.value.qosmap.count; j++) {
                      sai_thrift_parse_qos_map_params(&attribute.value.qosmap.map_list[j].key, &attr->value.qosmap.list[j].key);
                      sai_thrift_parse_qos_map_params(&attribute.value.qosmap.map_list[j].value, &attr->value.qosmap.list[j].value);
                  }
                  break;
          }
      }

      qos_map_api->create_qos_map(&qos_map_id, gSwitchId, thrift_attr_list.size(), attr_list);

      free(qos_map_list);
      free(attr_list);
      return qos_map_id;
  }

  void sai_thrift_parse_qos_map_params(const sai_thrift_qos_map_params_t *thrift_qos_params, sai_qos_map_params_t *qos_params) {
      qos_params->tc = thrift_qos_params->tc;
      qos_params->dscp = thrift_qos_params->dscp;
      qos_params->dot1p = thrift_qos_params->dot1p;
      qos_params->prio = thrift_qos_params->prio;
      qos_params->pg = thrift_qos_params->pg;
      qos_params->queue_index = thrift_qos_params->queue_index;
      qos_params->color = (sai_packet_color_t) thrift_qos_params->color;
  }

  void sai_thrift_parse_qos_map_params(const sai_qos_map_params_t *qos_params, sai_thrift_qos_map_params_t *thrift_qos_params) {
      thrift_qos_params->tc = qos_params->tc;
      thrift_qos_params->dscp = qos_params->dscp;
      thrift_qos_params->dot1p = qos_params->dot1p;
      thrift_qos_params->prio = qos_params->prio;
      thrift_qos_params->pg = qos_params->pg;
      thrift_qos_params->queue_index = qos_params->queue_index;
      thrift_qos_params->color = (sai_packet_color_t)qos_params->color;
  }

  sai_thrift_status_t sai_thrift_remove_qos_map(const sai_thrift_object_id_t qos_map_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_qos_map_api_t *qos_map_api;

      printf("sai_thrift_remove_qos_map\n");

      status = sai_api_query(SAI_API_QOS_MAP, (void **) &qos_map_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }

      status = qos_map_api->remove_qos_map((sai_object_id_t) qos_map_id);
      return status;
  }

  void sai_thrift_get_qos_map_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t qos_map_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_qos_map_api_t *qos_map_api;
      uint32_t attr_count = 0;
      sai_attribute_t attr[2];
	  sai_thrift_attribute_t thrift_attr;
	  sai_thrift_qos_map_t map_list;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_QOS_MAP, (void **) &qos_map_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain qos_map api, status:%d", status);
          return;
      }

      attr[0].id = SAI_QOS_MAP_ATTR_TYPE;
      attr[1].id = SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST;
      attr_count = 2;
	  attr[1].value.qosmap.count = 64;
	  attr[1].value.qosmap.list = (sai_qos_map_t*)malloc(attr[1].value.qosmap.count * sizeof(sai_qos_map_t));

      status = qos_map_api->get_qos_map_attribute(qos_map_id, attr_count, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to get qos_map attr, status:%d", status);
          return;
      }

	  thrift_attr.id = attr[0].id;
	  thrift_attr.value.u32 = attr[0].value.u32;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[1].id;
	  thrift_attr.value.qosmap.count = attr[1].value.qosmap.count;

	  for (int index = 0; index < attr[1].value.qosmap.count; index++)
  	  {
  	  	  memset(&map_list, 0, sizeof(map_list));
		  //map_list.key.tc = attr[1].value.qosmap.list[index].key.tc;
		  sai_thrift_parse_qos_map_params(&attr[1].value.qosmap.list[index].key, &map_list.key);
          sai_thrift_parse_qos_map_params(&attr[1].value.qosmap.list[index].value, &map_list.value);
		  thrift_attr.value.qosmap.map_list.push_back(map_list);
  	  }
	  thrift_attr_list.attr_list.push_back(thrift_attr);

	  free(attr[1].value.qosmap.list);
  }

  sai_thrift_status_t sai_thrift_set_qos_map_attribute(const sai_thrift_object_id_t qos_map_id, const sai_thrift_attribute_t &thrift_attr)
  {
      sai_attribute_t attr;
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_qos_map_api_t *qos_map_api = NULL;
      sai_qos_map_t *qos_map_list = NULL;

	  if (thrift_attr.id != SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST)
  	  {
  	  	status= SAI_STATUS_NOT_SUPPORTED;
  	  	SAI_THRIFT_LOG_DBG("Error Exited.");return status;
  	  }

	  status = sai_api_query(SAI_API_QOS_MAP, (void **) &qos_map_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain qos_map api, status:%d", status);
          return status;
      }

	  attr.id = thrift_attr.id;
      attr.value.qosmap.count = thrift_attr.value.qosmap.count;

      qos_map_list = (sai_qos_map_t *) malloc(attr.value.qosmap.count * sizeof(sai_qos_map_t));
      attr.value.qosmap.list = qos_map_list;

      for (uint32_t j = 0; j < thrift_attr.value.qosmap.count; j++) {
          sai_thrift_parse_qos_map_params(&thrift_attr.value.qosmap.map_list[j].key, &attr.value.qosmap.list[j].key);
          sai_thrift_parse_qos_map_params(&thrift_attr.value.qosmap.map_list[j].value, &attr.value.qosmap.list[j].value);
      }

	  status = qos_map_api->set_qos_map_attribute(qos_map_id, &attr);

      free(qos_map_list);
      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited.");return status; }

      SAI_THRIFT_LOG_ERR("Failed to set attribute.");

      return status;
  }
    //
    // SAI Next Hop Group API *****************************************************************************************
    //

    void sai_thrift_parse_next_hop_group_attributes
    (sai_attribute_t *attr_list, const std::vector<sai_thrift_attribute_t> &thrift_attr_list) noexcept
    {
        if (thrift_attr_list.empty() || attr_list == nullptr) { SAI_THRIFT_LOG_ERR("Invalid input arguments."); }

        std::vector<sai_thrift_attribute_t>::const_iterator cit = thrift_attr_list.begin();

        for (sai_uint32_t i = 0; i < thrift_attr_list.size(); i++, cit++)
        {
            sai_thrift_attribute_t attribute = *cit;
            attr_list[i].id = attribute.id;

            switch (attribute.id)
            {
                case SAI_NEXT_HOP_GROUP_ATTR_TYPE:
                    attr_list[i].value.s32 = attribute.value.s32;
                    break;

                case SAI_NEXT_HOP_GROUP_ATTR_SET_SWITCHOVER:
                    attr_list[i].value.booldata = attribute.value.booldata;
                    break;

                default:
                    SAI_THRIFT_LOG_ERR("Failed to parse attributes.");
                    break;
            }
        }
    }

    sai_thrift_object_id_t sai_thrift_create_next_hop_group
    (const std::vector<sai_thrift_attribute_t> &thrift_attr_list) noexcept
    {
        SAI_THRIFT_LOG_DBG("Called.");

        sai_next_hop_group_api_t *nhop_group_api = nullptr;
        auto status = sai_api_query(SAI_API_NEXT_HOP_GROUP, reinterpret_cast<void**>(&nhop_group_api));

        if (status != SAI_STATUS_SUCCESS)
        { SAI_THRIFT_LOG_ERR("Failed to get API."); return SAI_NULL_OBJECT_ID; }

        sai_attribute_t *attr_list = nullptr;
        sai_uint32_t attr_size = thrift_attr_list.size();
        sai_thrift_alloc_attr(attr_list, attr_size);
        sai_thrift_parse_next_hop_group_attributes(attr_list, thrift_attr_list);

        sai_object_id_t nhop_group_oid = 0;
        status = nhop_group_api->create_next_hop_group(&nhop_group_oid, gSwitchId, attr_size, attr_list);
        sai_thrift_free_attr(attr_list);

        if (status == SAI_STATUS_SUCCESS)
        { SAI_THRIFT_LOG_DBG("Exited."); return nhop_group_oid; }

        SAI_THRIFT_LOG_ERR("Failed to create next hop group, status:%d", status);

        return SAI_NULL_OBJECT_ID;
    }

    sai_thrift_status_t sai_thrift_remove_next_hop_group
    (const sai_thrift_object_id_t nhop_group_oid) noexcept
    {
        SAI_THRIFT_LOG_DBG("Called.");

        sai_next_hop_group_api_t *nhop_group_api = nullptr;
        auto status = sai_api_query(SAI_API_NEXT_HOP_GROUP, reinterpret_cast<void**>(&nhop_group_api));

        if (status != SAI_STATUS_SUCCESS)
        { SAI_THRIFT_LOG_ERR("Failed to get API."); return status; }

        status = nhop_group_api->remove_next_hop_group(nhop_group_oid);

        if (status != SAI_STATUS_SUCCESS)
        {
            SAI_THRIFT_LOG_ERR("Failed to remove next hop group, status:%d", status);
        }

        return status;
    }

     sai_thrift_status_t sai_thrift_set_next_hop_group_attribute(const sai_thrift_object_id_t nhop_group_oid,
                                                              const sai_thrift_attribute_t& thrift_attr)
     {
         printf("sai_thrift_set_next_hop_group_attribute\n");
         sai_status_t status = SAI_STATUS_SUCCESS;
         sai_next_hop_group_api_t *nhop_group_api;
         sai_attribute_t attr;
         const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

         status = sai_api_query(SAI_API_NEXT_HOP_GROUP, (void **) &nhop_group_api);
         if (status != SAI_STATUS_SUCCESS) {
             SAI_THRIFT_LOG_ERR("failed to set next hop group  attributes, status:%d", status);
             return status;
         }
         sai_thrift_parse_next_hop_group_attributes(&attr, thrift_attr_list);

         return nhop_group_api->set_next_hop_group_attribute(nhop_group_oid, &attr);
     }

    void sai_thrift_get_next_hop_group_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t nhop_group_oid) {
      printf("sai_thrift_get_next_hop_group_attribute\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_next_hop_group_api_t *nhop_group_api;
      sai_attribute_t attr[SAI_NEXT_HOP_GROUP_ATTR_END];
      uint32_t attr_cnt = 0;
      sai_object_list_t *member_list_object;
      sai_thrift_attribute_t thrift_attr;

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_NEXT_HOP_GROUP, (void **) &nhop_group_api);
      if (status != SAI_STATUS_SUCCESS) {
          return;
      }

      attr[0].value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * 128);
      attr[0].value.objlist.count = 128;

      attr[attr_cnt++].id = SAI_NEXT_HOP_GROUP_ATTR_NEXT_HOP_MEMBER_LIST;
      attr[attr_cnt++].id = SAI_NEXT_HOP_GROUP_ATTR_NEXT_HOP_COUNT;
      attr[attr_cnt++].id = SAI_NEXT_HOP_GROUP_ATTR_TYPE;
      attr[attr_cnt++].id = SAI_NEXT_HOP_GROUP_ATTR_SET_SWITCHOVER;


      status = nhop_group_api->get_next_hop_group_attribute(nhop_group_oid, attr_cnt, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("Failed to get next hop group attributes, status:%d", status);
          thrift_attr_list.status = status;
          free(attr[0].value.objlist.list);
          return;
      }

      thrift_attr.id        = attr[0].id;
      thrift_attr.value.objlist.count = attr[0].value.objlist.count;
      std :: vector < sai_thrift_object_id_t > & member_list = thrift_attr.value.objlist.object_id_list;
      member_list_object = &attr[0].value.objlist;
      for (int index = 0; index < attr[0].value.objlist.count; index++)
      {
          member_list.push_back((sai_thrift_object_id_t) member_list_object->list[index]);
      }
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = attr[1].id;
      thrift_attr.value.u32 = attr[1].value.u32;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = attr[2].id;
      thrift_attr.value.s32 = attr[2].value.s32;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id        = attr[3].id;
      thrift_attr.value.booldata = attr[3].value.booldata;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      free(attr[0].value.objlist.list);

  }

    void sai_thrift_parse_next_hop_group_member_attributes
    (sai_attribute_t *attr_list, const std::vector<sai_thrift_attribute_t> &thrift_attr_list) noexcept
    {
        if (thrift_attr_list.empty() || attr_list == nullptr) { SAI_THRIFT_LOG_ERR("Invalid input arguments."); }

        std::vector<sai_thrift_attribute_t>::const_iterator cit = thrift_attr_list.begin();

        for (sai_uint32_t i = 0; i < thrift_attr_list.size(); i++, cit++)
        {
            sai_thrift_attribute_t attribute = *cit;
            attr_list[i].id = attribute.id;

            switch (attribute.id)
            {
                case SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID:
                case SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID:
                    attr_list[i].value.oid = attribute.value.oid;
                    break;

                case SAI_NEXT_HOP_GROUP_MEMBER_ATTR_WEIGHT:
                    attr_list[i].value.u32 = attribute.value.u32;
                    break;

                case SAI_NEXT_HOP_GROUP_MEMBER_ATTR_CONFIGURED_ROLE:
                    attr_list[i].value.s32 = attribute.value.s32;
                    break;

                default:
                    SAI_THRIFT_LOG_ERR("Failed to parse attributes.");
                    break;
            }
        }
    }

    sai_thrift_object_id_t sai_thrift_create_next_hop_group_member
    (const std::vector<sai_thrift_attribute_t> &thrift_attr_list) noexcept
    {
        SAI_THRIFT_LOG_DBG("Called.");

        sai_next_hop_group_api_t *nhop_group_api = nullptr;
        auto status = sai_api_query(SAI_API_NEXT_HOP_GROUP, reinterpret_cast<void**>(&nhop_group_api));

        if (status != SAI_STATUS_SUCCESS)
        { SAI_THRIFT_LOG_ERR("Failed to get API."); return SAI_NULL_OBJECT_ID; }

        sai_attribute_t *attr_list = nullptr;
        sai_uint32_t attr_size = thrift_attr_list.size();
        sai_thrift_alloc_attr(attr_list, attr_size);
        sai_thrift_parse_next_hop_group_member_attributes(attr_list, thrift_attr_list);

        sai_object_id_t nhop_group_member_oid = 0;
        status = nhop_group_api->create_next_hop_group_member(&nhop_group_member_oid, gSwitchId, attr_size, attr_list);
        sai_thrift_free_attr(attr_list);

        if (status == SAI_STATUS_SUCCESS)
        { SAI_THRIFT_LOG_DBG("Exited."); return nhop_group_member_oid; }

        SAI_THRIFT_LOG_ERR("Failed to create group member.");

        return SAI_NULL_OBJECT_ID;
    }

    sai_thrift_status_t sai_thrift_remove_next_hop_group_member
    (const sai_thrift_object_id_t nhop_group_member_oid) noexcept
    {
        SAI_THRIFT_LOG_DBG("Called.");

        sai_next_hop_group_api_t *nhop_group_api = nullptr;
        auto status = sai_api_query(SAI_API_NEXT_HOP_GROUP, reinterpret_cast<void**>(&nhop_group_api));

        if (status != SAI_STATUS_SUCCESS)
        { SAI_THRIFT_LOG_ERR("Failed to get API."); return status; }

        status = nhop_group_api->remove_next_hop_group_member(nhop_group_member_oid);

        SAI_THRIFT_LOG_DBG("Exited.");

        return status;
    }

    void sai_thrift_get_next_hop_group_member_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t nhop_group_member_oid) {
          printf("sai_thrift_get_next_hop_group_member_attribute\n");
          sai_status_t status = SAI_STATUS_SUCCESS;
          sai_next_hop_group_api_t *nhop_group_api;
          sai_attribute_t attr[SAI_NEXT_HOP_GROUP_MEMBER_ATTR_END];
          uint32_t attr_cnt = 0;
          sai_thrift_attribute_t thrift_attr;

          thrift_attr_list.attr_count = 0;

          status = sai_api_query(SAI_API_NEXT_HOP_GROUP, (void **) &nhop_group_api);
          if (status != SAI_STATUS_SUCCESS) {
              return;
          }

          attr[attr_cnt++].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID;
          attr[attr_cnt++].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID;
          attr[attr_cnt++].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_CONFIGURED_ROLE;
          attr[attr_cnt++].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_OBSERVED_ROLE;

          status = nhop_group_api->get_next_hop_group_member_attribute(nhop_group_member_oid, attr_cnt, attr);
          if (status != SAI_STATUS_SUCCESS) {
              SAI_THRIFT_LOG_ERR("failed to get next hop group member attributes, status:%d", status);
              thrift_attr_list.status = status;
              return;
          }

          thrift_attr.id        = attr[0].id;
          thrift_attr.value.oid = attr[0].value.oid;
          thrift_attr_list.attr_list.push_back(thrift_attr);

          thrift_attr.id        = attr[1].id;
          thrift_attr.value.oid = attr[1].value.oid;
          thrift_attr_list.attr_list.push_back(thrift_attr);

          thrift_attr.id        = attr[2].id;
          thrift_attr.value.s32 = attr[2].value.s32;
          thrift_attr_list.attr_list.push_back(thrift_attr);

          thrift_attr.id        = attr[3].id;
          thrift_attr.value.s32 = attr[3].value.s32;
          thrift_attr_list.attr_list.push_back(thrift_attr);

      }

	sai_thrift_object_id_t sai_thrift_create_l2mc_group(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      printf("sai_thrift_create_l2mc_group\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_l2mc_group_api_t *l2mc_grp_api;
      sai_object_id_t	grp_id;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_L2MC_GROUP, (void **) &l2mc_grp_api);
      if (status != SAI_STATUS_SUCCESS) {
         return status;
      }

      status = l2mc_grp_api->create_l2mc_group(&grp_id, gSwitchId, 0, NULL);

      return grp_id;
  }

	sai_thrift_status_t sai_thrift_remove_l2mc_group(const sai_thrift_object_id_t grp_id) {
      printf("sai_thrift_remove_l2mc_group\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_l2mc_group_api_t *l2mc_grp_api;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_L2MC_GROUP, (void **) &l2mc_grp_api);
      if (status != SAI_STATUS_SUCCESS) {
         return status;
      }

      status = l2mc_grp_api->remove_l2mc_group(grp_id);

      return status;
  }

	void sai_thrift_get_l2mc_group_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t grp_id) {
      sai_l2mc_group_api_t *l2mc_grp_api;
      uint32_t attr_count = 0;
      sai_attribute_t attr[4];
	  sai_thrift_attribute_t thrift_attr;
	  sai_object_list_t *member_list_object;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      thrift_attr_list.status = sai_api_query(SAI_API_L2MC_GROUP, (void **) &l2mc_grp_api);
      if (thrift_attr_list.status != SAI_STATUS_SUCCESS) {
          return;
      }

	attr_count = 2;
      attr[0].id = SAI_L2MC_GROUP_ATTR_L2MC_OUTPUT_COUNT;
      attr[1].id = SAI_L2MC_GROUP_ATTR_L2MC_MEMBER_LIST;
      attr[1].value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * 128);
      attr[1].value.objlist.count = 128;

      thrift_attr_list.status = l2mc_grp_api->get_l2mc_group_attribute(grp_id, attr_count, attr);
      if (thrift_attr_list.status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain l2mc group attribute, status:%d", thrift_attr_list.status);
		  free(attr[1].value.objlist.list);
          return;
      }

		thrift_attr.id = attr[0].id;
	  thrift_attr.value.u16 = attr[0].value.u16;
		thrift_attr_list.attr_list.push_back(thrift_attr);

	thrift_attr.id = attr[1].id;
	thrift_attr.value.objlist.count = attr[1].value.objlist.count;
	  std::vector<sai_thrift_object_id_t>& member_list = thrift_attr.value.objlist.object_id_list;
      member_list_object = &attr[1].value.objlist;
      for (int index = 0; index < attr[1].value.objlist.count; index++) {
          member_list.push_back((sai_thrift_object_id_t) member_list_object->list[index]);
      }
      thrift_attr_list.attr_list.push_back(thrift_attr);
		free(attr[1].value.objlist.list);
  }

	void sai_thrift_parse_l2mc_group_member_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;

          switch (attribute.id) {
              case SAI_L2MC_GROUP_MEMBER_ATTR_L2MC_GROUP_ID:
              case SAI_L2MC_GROUP_MEMBER_ATTR_L2MC_OUTPUT_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;

              default:
                  SAI_THRIFT_LOG_ERR("Failed to parse l2mc member attributes.");
                  break;
          }
      }
  }

	sai_thrift_object_id_t sai_thrift_create_l2mc_group_member(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      printf("sai_thrift_create_l2mc_group_member\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_l2mc_group_api_t *l2mc_grp_api;
		sai_attribute_t  *sai_attrs = nullptr;
		sai_object_id_t	member_oid;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_L2MC_GROUP, (void **) &l2mc_grp_api);
      if (status != SAI_STATUS_SUCCESS) {
         return status;
      }

	sai_uint32_t attr_size = thrift_attr_list.size();

      sai_thrift_alloc_attr(sai_attrs, attr_size);

	sai_thrift_parse_l2mc_group_member_attributes(thrift_attr_list, sai_attrs);

      status = l2mc_grp_api->create_l2mc_group_member(&member_oid, gSwitchId, attr_size, sai_attrs);

      return member_oid;
  }

	sai_thrift_status_t sai_thrift_remove_l2mc_group_member(const sai_thrift_object_id_t member_id) {
      printf("sai_thrift_remove_l2mc_group_member\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_l2mc_group_api_t *l2mc_grp_api;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_L2MC_GROUP, (void **) &l2mc_grp_api);
      if (status != SAI_STATUS_SUCCESS) {
         return status;
      }

      status = l2mc_grp_api->remove_l2mc_group_member(member_id);

      return status;
  }

	sai_thrift_status_t sai_thrift_set_l2mc_group_member_attribute(const sai_thrift_object_id_t member_id,
                                                           const sai_thrift_attribute_t& thrift_attr)
  {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_l2mc_group_api_t *l2mc_grp_api;
      sai_attribute_t attr;
      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_L2MC_GROUP, (void **) &l2mc_grp_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain l2mc_grp_api, status:%d", status);
          return status;
      }

      sai_thrift_parse_l2mc_group_member_attributes(thrift_attr_list, &attr);

      return l2mc_grp_api->set_l2mc_group_member_attribute(member_id, &attr);
  }

	void sai_thrift_get_l2mc_group_member_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t member_id) {
      sai_l2mc_group_api_t *l2mc_grp_api;
      uint32_t attr_count = 0;
      sai_attribute_t attr[4];
	  sai_thrift_attribute_t thrift_attr;
	  sai_object_list_t *member_list_object;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      thrift_attr_list.status = sai_api_query(SAI_API_L2MC_GROUP, (void **) &l2mc_grp_api);
      if (thrift_attr_list.status != SAI_STATUS_SUCCESS) {
          return;
      }

	attr_count = 2;
      attr[0].id = SAI_L2MC_GROUP_MEMBER_ATTR_L2MC_GROUP_ID;
      attr[1].id = SAI_L2MC_GROUP_MEMBER_ATTR_L2MC_OUTPUT_ID;

      thrift_attr_list.status = l2mc_grp_api->get_l2mc_group_member_attribute(member_id, attr_count, attr);
      if (thrift_attr_list.status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain l2mc group member attribute, status:%d", thrift_attr_list.status);
          return;
      }

		thrift_attr.id = attr[0].id;
	  thrift_attr.value.oid = attr[0].value.oid;
		thrift_attr_list.attr_list.push_back(thrift_attr);

		thrift_attr.id = attr[1].id;
	  thrift_attr.value.oid = attr[1].value.oid;
		thrift_attr_list.attr_list.push_back(thrift_attr);
  }

	void sai_thrift_parse_l2mc_entry_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;

          switch (attribute.id) {
			case SAI_L2MC_ENTRY_ATTR_PACKET_ACTION:
				attr_list[i].value.s32 = attribute.value.s32;
				break;

              case SAI_L2MC_ENTRY_ATTR_OUTPUT_GROUP_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;

              default:
                  SAI_THRIFT_LOG_ERR("Failed to parse l2mc member attributes.");
                  break;
          }
      }
  }

	sai_thrift_status_t sai_thrift_create_l2mc_entry(const sai_thrift_l2mc_entry_t &thrift_l2mc_entry,
                                                           const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      printf("sai_thrift_create_l2mc_entry\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_l2mc_api_t *l2mc_api;
      sai_l2mc_entry_t l2mc_entry;
      sai_attribute_t  *sai_attrs = nullptr;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_L2MC, (void **) &l2mc_api);
      if (status != SAI_STATUS_SUCCESS) {
         return status;
      }

	sai_thrift_parse_l2mc_entry(thrift_l2mc_entry, &l2mc_entry);

	sai_uint32_t attr_size = thrift_attr_list.size();

      sai_thrift_alloc_attr(sai_attrs, attr_size);

	sai_thrift_parse_l2mc_entry_attributes(thrift_attr_list, sai_attrs);

      status = l2mc_api->create_l2mc_entry(&l2mc_entry, attr_size, sai_attrs);

      return status;
  }

	sai_thrift_status_t sai_thrift_remove_l2mc_entry(const sai_thrift_l2mc_entry_t &thrift_l2mc_entry) {
      printf("sai_thrift_remove_l2mc_entry\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_l2mc_api_t *l2mc_api;
      sai_l2mc_entry_t l2mc_entry;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_L2MC, (void **) &l2mc_api);
      if (status != SAI_STATUS_SUCCESS) {
         return status;
      }

	sai_thrift_parse_l2mc_entry(thrift_l2mc_entry, &l2mc_entry);

      status = l2mc_api->remove_l2mc_entry(&l2mc_entry);

      return status;
  }

	sai_thrift_status_t sai_thrift_set_l2mc_entry_attribute(const sai_thrift_l2mc_entry_t &thrift_l2mc_entry,
                                                           const sai_thrift_attribute_t& thrift_attr) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_l2mc_api_t *l2mc_api;
      sai_l2mc_entry_t l2mc_entry;
      sai_attribute_t attr;
      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_L2MC, (void **) &l2mc_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain l2mc_api, status:%d", status);
          return status;
      }

	sai_thrift_parse_l2mc_entry(thrift_l2mc_entry, &l2mc_entry);
      sai_thrift_parse_l2mc_entry_attributes(thrift_attr_list, &attr);

      return l2mc_api->set_l2mc_entry_attribute(&l2mc_entry, &attr);
  }

	void sai_thrift_get_l2mc_entry_attribute(sai_thrift_attribute_list_t& thrift_attr_list,
                                                           const sai_thrift_l2mc_entry_t &thrift_l2mc_entry) {
      sai_l2mc_api_t *l2mc_api;
      sai_l2mc_entry_t l2mc_entry;
      uint32_t attr_count = 0;
      sai_attribute_t attr[4];
	  sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      thrift_attr_list.status = sai_api_query(SAI_API_L2MC, (void **) &l2mc_api);
      if (thrift_attr_list.status != SAI_STATUS_SUCCESS) {
          return;
      }

      attr_count = 2;
      attr[0].id = SAI_L2MC_ENTRY_ATTR_PACKET_ACTION;
      attr[1].id = SAI_L2MC_ENTRY_ATTR_OUTPUT_GROUP_ID;

      sai_thrift_parse_l2mc_entry(thrift_l2mc_entry, &l2mc_entry);
      thrift_attr_list.status = l2mc_api->get_l2mc_entry_attribute(&l2mc_entry, attr_count, attr);
      if (thrift_attr_list.status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain l2mc entry attribute, status:%d", thrift_attr_list.status);
          return;
      }

		thrift_attr.id = attr[0].id;
	  thrift_attr.value.s32 = attr[0].value.s32;
		thrift_attr_list.attr_list.push_back(thrift_attr);

		thrift_attr.id = attr[1].id;
	  thrift_attr.value.oid = attr[1].value.oid;
		thrift_attr_list.attr_list.push_back(thrift_attr);
  }

	void sai_thrift_parse_mcast_fdb_entry_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;

          switch (attribute.id)
          {
              case SAI_MCAST_FDB_ENTRY_ATTR_PACKET_ACTION:
                  attr_list[i].value.s32 = attribute.value.s32;
                  break;

              case SAI_MCAST_FDB_ENTRY_ATTR_GROUP_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;

              case SAI_MCAST_FDB_ENTRY_ATTR_META_DATA:
                  attr_list[i].value.u32 = attribute.value.u32;
                  break;

              default:
                  SAI_THRIFT_LOG_ERR("Failed to parse mcast fdb entry attributes.");
                  break;
          }
      }
  }

	sai_thrift_status_t sai_thrift_create_mcast_fdb_entry(const sai_thrift_mcast_fdb_entry_t &thrift_mcast_fdb_entry,
                                                           const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      printf("sai_thrift_create_mcast_fdb_entry\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_mcast_fdb_api_t *mcast_fdb_api;
      sai_mcast_fdb_entry_t mcast_fdb_entry;
      sai_attribute_t  *sai_attrs = nullptr;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_MCAST_FDB, (void **) &mcast_fdb_api);
      if (status != SAI_STATUS_SUCCESS) {
         return status;
      }

	sai_thrift_parse_mcast_fdb_entry(thrift_mcast_fdb_entry, &mcast_fdb_entry);

	sai_uint32_t attr_size = thrift_attr_list.size();

      sai_thrift_alloc_attr(sai_attrs, attr_size);

	sai_thrift_parse_mcast_fdb_entry_attributes(thrift_attr_list, sai_attrs);

      status = mcast_fdb_api->create_mcast_fdb_entry(&mcast_fdb_entry, attr_size, sai_attrs);

      return status;
  }

	sai_thrift_status_t sai_thrift_remove_mcast_fdb_entry(const sai_thrift_mcast_fdb_entry_t &thrift_mcast_fdb_entry) {
      printf("sai_thrift_remove_mcast_fdb_entry\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_mcast_fdb_api_t *mcast_fdb_api;
      sai_mcast_fdb_entry_t mcast_fdb_entry;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_MCAST_FDB, (void **) &mcast_fdb_api);
      if (status != SAI_STATUS_SUCCESS) {
         return status;
      }

	sai_thrift_parse_mcast_fdb_entry(thrift_mcast_fdb_entry, &mcast_fdb_entry);

      status = mcast_fdb_api->remove_mcast_fdb_entry(&mcast_fdb_entry);

      return status;
  }

	sai_thrift_status_t sai_thrift_set_mcast_fdb_entry_attribute(const sai_thrift_mcast_fdb_entry_t &thrift_mcast_fdb_entry,
                                                           const sai_thrift_attribute_t& thrift_attr) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_mcast_fdb_api_t *mcast_fdb_api;
      sai_mcast_fdb_entry_t mcast_fdb_entry;
      sai_attribute_t attr;
      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_MCAST_FDB, (void **) &mcast_fdb_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain mcast_fdb_api, status:%d", status);
          return status;
      }

	sai_thrift_parse_mcast_fdb_entry(thrift_mcast_fdb_entry, &mcast_fdb_entry);
      sai_thrift_parse_mcast_fdb_entry_attributes(thrift_attr_list, &attr);

      return mcast_fdb_api->set_mcast_fdb_entry_attribute(&mcast_fdb_entry, &attr);
  }

	void sai_thrift_get_mcast_fdb_entry_attribute(sai_thrift_attribute_list_t& thrift_attr_list,
                                                           const sai_thrift_mcast_fdb_entry_t &thrift_mcast_fdb_entry) {
      sai_mcast_fdb_api_t *mcast_fdb_api;
      sai_mcast_fdb_entry_t mcast_fdb_entry;
      uint32_t attr_count = 0;
      sai_attribute_t attr[4];
	  sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      thrift_attr_list.status = sai_api_query(SAI_API_MCAST_FDB, (void **) &mcast_fdb_api);
      if (thrift_attr_list.status != SAI_STATUS_SUCCESS) {
          return;
      }

      attr_count = 3;
      attr[0].id = SAI_MCAST_FDB_ENTRY_ATTR_PACKET_ACTION;
      attr[1].id = SAI_MCAST_FDB_ENTRY_ATTR_GROUP_ID;
      attr[2].id = SAI_MCAST_FDB_ENTRY_ATTR_META_DATA;

      sai_thrift_parse_mcast_fdb_entry(thrift_mcast_fdb_entry, &mcast_fdb_entry);
      thrift_attr_list.status = mcast_fdb_api->get_mcast_fdb_entry_attribute(&mcast_fdb_entry, attr_count, attr);
      if (thrift_attr_list.status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain mcast fdb entry attribute, status:%d", thrift_attr_list.status);
          return;
      }

      thrift_attr.id = attr[0].id;
      thrift_attr.value.s32 = attr[0].value.s32;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id = attr[1].id;
      thrift_attr.value.oid = attr[1].value.oid;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id = attr[2].id;
      thrift_attr.value.u32 = attr[2].value.u32;
      thrift_attr_list.attr_list.push_back(thrift_attr);
  }

  sai_thrift_object_id_t sai_thrift_create_ipmc_group(const std :: vector < sai_thrift_attribute_t > & thrift_attr_list)
  {
      printf("sai_thrift_create_ipmc_group\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_ipmc_group_api_t *ipmc_grp_api;
      sai_object_id_t	grp_id;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_IPMC_GROUP, (void **) &ipmc_grp_api);
      if (status != SAI_STATUS_SUCCESS) {
         return status;
      }

      status = ipmc_grp_api->create_ipmc_group(&grp_id, gSwitchId, 0, NULL);

      return grp_id;
  }

	sai_thrift_status_t sai_thrift_remove_ipmc_group(const sai_thrift_object_id_t grp_id) {
      printf("sai_thrift_remove_ipmc_group\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_ipmc_group_api_t *ipmc_grp_api;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_IPMC_GROUP, (void **) &ipmc_grp_api);
      if (status != SAI_STATUS_SUCCESS) {
         return status;
      }

      status = ipmc_grp_api->remove_ipmc_group(grp_id);

      return status;
  }

	void sai_thrift_get_ipmc_group_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t grp_id) {
      sai_ipmc_group_api_t *ipmc_grp_api;
      uint32_t attr_count = 0;
      sai_attribute_t attr[4];
	  sai_thrift_attribute_t thrift_attr;
	  sai_object_list_t *member_list_object;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      thrift_attr_list.status = sai_api_query(SAI_API_IPMC_GROUP, (void **) &ipmc_grp_api);
      if (thrift_attr_list.status != SAI_STATUS_SUCCESS) {
          return;
      }

	attr_count = 2;
      attr[0].id = SAI_IPMC_GROUP_ATTR_IPMC_OUTPUT_COUNT;
      attr[1].id = SAI_IPMC_GROUP_ATTR_IPMC_MEMBER_LIST;
      attr[1].value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * 128);
      attr[1].value.objlist.count = 128;

      thrift_attr_list.status = ipmc_grp_api->get_ipmc_group_attribute(grp_id, attr_count, attr);
      if (thrift_attr_list.status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain ipmc group attribute, status:%d", thrift_attr_list.status);
		  free(attr[1].value.objlist.list);
          return;
      }

		thrift_attr.id = attr[0].id;
	  thrift_attr.value.u16 = attr[0].value.u16;
		thrift_attr_list.attr_list.push_back(thrift_attr);

	thrift_attr.id = attr[1].id;
	thrift_attr.value.objlist.count = attr[1].value.objlist.count;
	  std::vector<sai_thrift_object_id_t>& member_list = thrift_attr.value.objlist.object_id_list;
      member_list_object = &attr[1].value.objlist;
      for (int index = 0; index < attr[1].value.objlist.count; index++) {
          member_list.push_back((sai_thrift_object_id_t) member_list_object->list[index]);
      }
      thrift_attr_list.attr_list.push_back(thrift_attr);
		free(attr[1].value.objlist.list);
  }

	void sai_thrift_parse_ipmc_group_member_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;

          switch (attribute.id) {
              case SAI_IPMC_GROUP_MEMBER_ATTR_IPMC_GROUP_ID:
              case SAI_IPMC_GROUP_MEMBER_ATTR_IPMC_OUTPUT_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;

              default:
                  SAI_THRIFT_LOG_ERR("Failed to parse ipmc member attributes.");
                  break;
          }
      }
  }

	sai_thrift_object_id_t sai_thrift_create_ipmc_group_member(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      printf("sai_thrift_create_ipmc_group_member\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_ipmc_group_api_t *ipmc_grp_api;
		sai_attribute_t  *sai_attrs = nullptr;
		sai_object_id_t	member_oid;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_IPMC_GROUP, (void **) &ipmc_grp_api);
      if (status != SAI_STATUS_SUCCESS) {
         return status;
      }

	sai_uint32_t attr_size = thrift_attr_list.size();

      sai_thrift_alloc_attr(sai_attrs, attr_size);

	sai_thrift_parse_ipmc_group_member_attributes(thrift_attr_list, sai_attrs);

      status = ipmc_grp_api->create_ipmc_group_member(&member_oid, gSwitchId, attr_size, sai_attrs);

      return member_oid;
  }

	sai_thrift_status_t sai_thrift_remove_ipmc_group_member(const sai_thrift_object_id_t member_id) {
      printf("sai_thrift_remove_ipmc_group_member\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_ipmc_group_api_t *ipmc_grp_api;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_IPMC_GROUP, (void **) &ipmc_grp_api);
      if (status != SAI_STATUS_SUCCESS) {
         return status;
      }

      status = ipmc_grp_api->remove_ipmc_group_member(member_id);

      return status;
  }

	sai_thrift_status_t sai_thrift_set_ipmc_group_member_attribute(const sai_thrift_object_id_t member_id,
                                                           const sai_thrift_attribute_t& thrift_attr)
  {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_ipmc_group_api_t *ipmc_grp_api;
      sai_attribute_t attr;
      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_IPMC_GROUP, (void **) &ipmc_grp_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain ipmc_grp_api, status:%d", status);
          return status;
      }

      sai_thrift_parse_ipmc_group_member_attributes(thrift_attr_list, &attr);

      return ipmc_grp_api->set_ipmc_group_member_attribute(member_id, &attr);
  }

	void sai_thrift_get_ipmc_group_member_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t member_id) {
      sai_ipmc_group_api_t *ipmc_grp_api;
      uint32_t attr_count = 0;
      sai_attribute_t attr[4];
	  sai_thrift_attribute_t thrift_attr;
	  sai_object_list_t *member_list_object;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      thrift_attr_list.status = sai_api_query(SAI_API_IPMC_GROUP, (void **) &ipmc_grp_api);
      if (thrift_attr_list.status != SAI_STATUS_SUCCESS) {
          return;
      }

	attr_count = 2;
      attr[0].id = SAI_IPMC_GROUP_MEMBER_ATTR_IPMC_GROUP_ID;
      attr[1].id = SAI_IPMC_GROUP_MEMBER_ATTR_IPMC_OUTPUT_ID;

      thrift_attr_list.status = ipmc_grp_api->get_ipmc_group_member_attribute(member_id, attr_count, attr);
      if (thrift_attr_list.status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain ipmc group member attribute, status:%d", thrift_attr_list.status);
          return;
      }

		thrift_attr.id = attr[0].id;
	  thrift_attr.value.oid = attr[0].value.oid;
		thrift_attr_list.attr_list.push_back(thrift_attr);

		thrift_attr.id = attr[1].id;
	  thrift_attr.value.oid = attr[1].value.oid;
		thrift_attr_list.attr_list.push_back(thrift_attr);
  }

	void sai_thrift_parse_ipmc_entry_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;

          switch (attribute.id) {
			case SAI_IPMC_ENTRY_ATTR_PACKET_ACTION:
				attr_list[i].value.s32 = attribute.value.s32;
				break;

              case SAI_IPMC_ENTRY_ATTR_OUTPUT_GROUP_ID:
              case SAI_IPMC_ENTRY_ATTR_RPF_GROUP_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;

              default:
                  SAI_THRIFT_LOG_ERR("Failed to parse ipmc member attributes.");
                  break;
          }
      }
  }

	sai_thrift_object_id_t sai_thrift_create_rpf_group(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      printf("sai_thrift_create_rpf_group\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_rpf_group_api_t *rpf_grp_api;
		sai_object_id_t	grp_oid;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_RPF_GROUP, (void **) &rpf_grp_api);
      if (status != SAI_STATUS_SUCCESS) {
         return status;
      }

      status = rpf_grp_api->create_rpf_group(&grp_oid, gSwitchId, 0, NULL);

      return grp_oid;
  }

	sai_thrift_status_t sai_thrift_remove_rpf_group(const sai_thrift_object_id_t grp_id) {
      printf("sai_thrift_remove_rpf_group\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_rpf_group_api_t *rpf_grp_api;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_RPF_GROUP, (void **) &rpf_grp_api);
      if (status != SAI_STATUS_SUCCESS) {
         return status;
      }

      status = rpf_grp_api->remove_rpf_group(grp_id);

      return status;
  }

	void sai_thrift_get_rpf_group_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t grp_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_rpf_group_api_t *rpf_grp_api;
      uint32_t attr_count = 0;
      sai_attribute_t attr[4];
	  sai_thrift_attribute_t thrift_attr;
	  sai_object_list_t *member_list_object;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_RPF_GROUP, (void **) &rpf_grp_api);
      if (status != SAI_STATUS_SUCCESS) {
          return;
      }

      attr_count = 2;
      attr[0].id = SAI_RPF_GROUP_ATTR_RPF_INTERFACE_COUNT;
      attr[1].id = SAI_RPF_GROUP_ATTR_RPF_MEMBER_LIST;
      attr[1].value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * 16);
      attr[1].value.objlist.count = 16;

      status = rpf_grp_api->get_rpf_group_attribute(grp_id, attr_count, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain ipmc group attribute, status:%d", status);
		  free(attr[1].value.objlist.list);
          return;
      }

		thrift_attr.id = attr[0].id;
	  thrift_attr.value.u16 = attr[0].value.u16;
		thrift_attr_list.attr_list.push_back(thrift_attr);

	thrift_attr.id = attr[1].id;
	thrift_attr.value.objlist.count = attr[1].value.objlist.count;
	  std::vector<sai_thrift_object_id_t>& member_list = thrift_attr.value.objlist.object_id_list;
      member_list_object = &attr[1].value.objlist;
      for (int index = 0; index < attr[1].value.objlist.count; index++) {
          member_list.push_back((sai_thrift_object_id_t) member_list_object->list[index]);
      }
      thrift_attr_list.attr_list.push_back(thrift_attr);
		free(attr[1].value.objlist.list);
  }

	void sai_thrift_parse_rpf_group_member_attributes(const std::vector<sai_thrift_attribute_t> &thrift_attr_list, sai_attribute_t *attr_list) {
      std::vector<sai_thrift_attribute_t>::const_iterator it = thrift_attr_list.begin();
      sai_thrift_attribute_t attribute;
      for(uint32_t i = 0; i < thrift_attr_list.size(); i++, it++) {
          attribute = (sai_thrift_attribute_t)*it;
          attr_list[i].id = attribute.id;

          switch (attribute.id) {
              case SAI_RPF_GROUP_MEMBER_ATTR_RPF_GROUP_ID:
              case SAI_RPF_GROUP_MEMBER_ATTR_RPF_INTERFACE_ID:
                  attr_list[i].value.oid = attribute.value.oid;
                  break;

              default:
                  SAI_THRIFT_LOG_ERR("Failed to parse ipmc member attributes.");
                  break;
          }
      }
  }

sai_thrift_object_id_t sai_thrift_create_rpf_group_member(const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      printf("sai_thrift_create_rpf_group_member\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_rpf_group_api_t *rpf_grp_api;
		sai_attribute_t  *sai_attrs = nullptr;
		sai_object_id_t	member_oid;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_RPF_GROUP, (void **) &rpf_grp_api);
      if (status != SAI_STATUS_SUCCESS) {
         return status;
      }

	sai_uint32_t attr_size = thrift_attr_list.size();

      sai_thrift_alloc_attr(sai_attrs, attr_size);

	sai_thrift_parse_rpf_group_member_attributes(thrift_attr_list, sai_attrs);

      status = rpf_grp_api->create_rpf_group_member(&member_oid, gSwitchId, attr_size, sai_attrs);

      return member_oid;
  }

	sai_thrift_status_t sai_thrift_remove_rpf_group_member(const sai_thrift_object_id_t member_id) {
      printf("sai_thrift_remove_rpf_group_member\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_rpf_group_api_t *rpf_grp_api;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_RPF_GROUP, (void **) &rpf_grp_api);
      if (status != SAI_STATUS_SUCCESS) {
         return status;
      }

      status = rpf_grp_api->remove_rpf_group_member(member_id);

      return status;
  }

	sai_thrift_status_t sai_thrift_set_rpf_group_member_attribute(const sai_thrift_object_id_t member_id,
                                                           const sai_thrift_attribute_t& thrift_attr)
  {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_rpf_group_api_t *rpf_grp_api;
      sai_attribute_t attr;
      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_RPF_GROUP, (void **) &rpf_grp_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain rpf_grp_api, status:%d", status);
          return status;
      }

      sai_thrift_parse_rpf_group_member_attributes(thrift_attr_list, &attr);

      return rpf_grp_api->set_rpf_group_member_attribute(member_id, &attr);
  }

	void sai_thrift_get_rpf_group_member_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t member_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_rpf_group_api_t *rpf_grp_api;
      uint32_t attr_count = 0;
      sai_attribute_t attr[4];
	  sai_thrift_attribute_t thrift_attr;
	  sai_object_list_t *member_list_object;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_RPF_GROUP, (void **) &rpf_grp_api);
      if (status != SAI_STATUS_SUCCESS) {
          return;
      }

	attr_count = 2;
      attr[0].id = SAI_RPF_GROUP_MEMBER_ATTR_RPF_GROUP_ID;
      attr[1].id = SAI_RPF_GROUP_MEMBER_ATTR_RPF_INTERFACE_ID;

      status = rpf_grp_api->get_rpf_group_member_attribute(member_id, attr_count, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain rpf group member attribute, status:%d", status);
          return;
      }

		thrift_attr.id = attr[0].id;
	  thrift_attr.value.oid = attr[0].value.oid;
		thrift_attr_list.attr_list.push_back(thrift_attr);

		thrift_attr.id = attr[1].id;
	  thrift_attr.value.oid = attr[1].value.oid;
		thrift_attr_list.attr_list.push_back(thrift_attr);
  }

	sai_thrift_status_t sai_thrift_create_ipmc_entry(const sai_thrift_ipmc_entry_t &thrift_ipmc_entry,
                                                           const std::vector<sai_thrift_attribute_t> & thrift_attr_list) {
      printf("sai_thrift_create_ipmc_entry\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_ipmc_api_t *ipmc_api;
      sai_ipmc_entry_t ipmc_entry;
      sai_attribute_t  *sai_attrs = nullptr;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_IPMC, (void **) &ipmc_api);
      if (status != SAI_STATUS_SUCCESS) {
         return status;
      }

	sai_thrift_parse_ipmc_entry(thrift_ipmc_entry, &ipmc_entry);

	sai_uint32_t attr_size = thrift_attr_list.size();

      sai_thrift_alloc_attr(sai_attrs, attr_size);

	sai_thrift_parse_ipmc_entry_attributes(thrift_attr_list, sai_attrs);

      status = ipmc_api->create_ipmc_entry(&ipmc_entry, attr_size, sai_attrs);

      return status;
  }

	sai_thrift_status_t sai_thrift_remove_ipmc_entry(const sai_thrift_ipmc_entry_t &thrift_ipmc_entry) {
      printf("sai_thrift_remove_ipmc_entry\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_ipmc_api_t *ipmc_api;
      sai_ipmc_entry_t ipmc_entry;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_IPMC, (void **) &ipmc_api);
      if (status != SAI_STATUS_SUCCESS) {
         return status;
      }

	sai_thrift_parse_ipmc_entry(thrift_ipmc_entry, &ipmc_entry);

      status = ipmc_api->remove_ipmc_entry(&ipmc_entry);

      return status;
  }

	sai_thrift_status_t sai_thrift_set_ipmc_entry_attribute(const sai_thrift_ipmc_entry_t &thrift_ipmc_entry,
                                                           const sai_thrift_attribute_t& thrift_attr) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_ipmc_api_t *ipmc_api;
      sai_ipmc_entry_t ipmc_entry;
      sai_attribute_t attr;
      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_IPMC, (void **) &ipmc_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain ipmc_api, status:%d", status);
          return status;
      }

	sai_thrift_parse_ipmc_entry(thrift_ipmc_entry, &ipmc_entry);
      sai_thrift_parse_ipmc_entry_attributes(thrift_attr_list, &attr);

      return ipmc_api->set_ipmc_entry_attribute(&ipmc_entry, &attr);
  }

	void sai_thrift_get_ipmc_entry_attribute(sai_thrift_attribute_list_t& thrift_attr_list,
                                                           const sai_thrift_ipmc_entry_t &thrift_ipmc_entry) {
      sai_ipmc_api_t *ipmc_api;
      sai_ipmc_entry_t ipmc_entry;
      uint32_t attr_count = 0;
      sai_attribute_t attr[4];
	  sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      thrift_attr_list.status = sai_api_query(SAI_API_IPMC, (void **) &ipmc_api);
      if (thrift_attr_list.status != SAI_STATUS_SUCCESS) {
          return;
      }

      attr_count = 3;
      attr[0].id = SAI_IPMC_ENTRY_ATTR_PACKET_ACTION;
      attr[1].id = SAI_IPMC_ENTRY_ATTR_OUTPUT_GROUP_ID;
      attr[2].id = SAI_IPMC_ENTRY_ATTR_RPF_GROUP_ID;

      sai_thrift_parse_ipmc_entry(thrift_ipmc_entry, &ipmc_entry);
      thrift_attr_list.status = ipmc_api->get_ipmc_entry_attribute(&ipmc_entry, attr_count, attr);
      if (thrift_attr_list.status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain ipmc entry attribute, status:%d", thrift_attr_list.status);
          return;
      }

		thrift_attr.id = attr[0].id;
	  thrift_attr.value.s32 = attr[0].value.s32;
		thrift_attr_list.attr_list.push_back(thrift_attr);

		thrift_attr.id = attr[1].id;
	  thrift_attr.value.oid = attr[1].value.oid;
		thrift_attr_list.attr_list.push_back(thrift_attr);

		thrift_attr.id = attr[2].id;
	  thrift_attr.value.oid = attr[2].value.oid;
		thrift_attr_list.attr_list.push_back(thrift_attr);
  }

  sai_thrift_object_id_t sai_thrift_create_samplepacket(const std::vector<sai_thrift_attribute_t> &thrift_attr_list) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_samplepacket_api_t *samplepacket_api = nullptr;
      auto status = sai_api_query(SAI_API_SAMPLEPACKET, reinterpret_cast<void**>(&samplepacket_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return SAI_NULL_OBJECT_ID; }

      sai_attribute_t *attr_list = nullptr;
      sai_size_t attr_size = thrift_attr_list.size();
      sai_thrift_alloc_attr(attr_list, attr_size);
      sai_thrift_parse_samplepacket_attributes(thrift_attr_list, attr_list);

      sai_object_id_t samplepacket_oid = 0;
      status = samplepacket_api->create_samplepacket(&samplepacket_oid, gSwitchId, attr_size, attr_list);
      sai_thrift_free_attr(attr_list);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return samplepacket_oid; }

      SAI_THRIFT_LOG_ERR("Failed to create OID.");

      return SAI_NULL_OBJECT_ID;
  }

  sai_thrift_status_t sai_thrift_remove_samplepacket(const sai_thrift_object_id_t samplepacket_id)
  {
      sai_samplepacket_api_t *samplepacket_api;
      sai_status_t status;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_SAMPLEPACKET, (void **) &samplepacket_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain samplepacket_api, status:%d", status);
          return status;
      }

      return samplepacket_api->remove_samplepacket((sai_object_id_t) samplepacket_id);
  }

  sai_thrift_status_t sai_thrift_set_samplepacket_attribute(const sai_thrift_object_id_t samplepacket_id,
                                                           const sai_thrift_attribute_t& thrift_attr)
  {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_samplepacket_api_t *samplepacket_api;
      sai_attribute_t attr;
      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_SAMPLEPACKET, (void **) &samplepacket_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain samplepacket_api, status:%d", status);
          return status;
      }

      sai_thrift_parse_samplepacket_attributes(thrift_attr_list, &attr);

      return samplepacket_api->set_samplepacket_attribute(samplepacket_id, &attr);
  }

  void sai_thrift_get_samplepacket_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t samplepacket_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_samplepacket_api_t *samplepacket_api;
      uint32_t attr_count = 0;
      sai_attribute_t attr[4];
	  sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_SAMPLEPACKET, (void **) &samplepacket_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain samplepacket_api, status:%d", status);
          return;
      }

      attr[0].id = SAI_SAMPLEPACKET_ATTR_SAMPLE_RATE;
      attr[1].id = SAI_SAMPLEPACKET_ATTR_TYPE;
	  attr[2].id = SAI_SAMPLEPACKET_ATTR_MODE;
      attr_count = 3;

      status = samplepacket_api->get_samplepacket_attribute(samplepacket_id, attr_count, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain samplepacket port type, status:%d", status);
          return;
      }

	  thrift_attr.id = attr[0].id;
	  thrift_attr.value.u32 = attr[0].value.u32;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[1].id;
	  thrift_attr.value.s32 = attr[1].value.s32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[2].id;
	  thrift_attr.value.s32 = attr[2].value.s32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
  }

  sai_thrift_object_id_t sai_thrift_create_tunnel_map_entry(const std::vector<sai_thrift_attribute_t> &thrift_attr_list) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_tunnel_api_t *tunnel_api = nullptr;
      auto status = sai_api_query(SAI_API_TUNNEL, reinterpret_cast<void**>(&tunnel_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return SAI_NULL_OBJECT_ID; }

      sai_attribute_t *attr_list = nullptr;
      sai_size_t attr_size = thrift_attr_list.size();
      sai_thrift_alloc_attr(attr_list, attr_size);
      sai_thrift_parse_tunnel_map_entry_attributes(thrift_attr_list, attr_list);

      sai_object_id_t tunnel_map_entry_oid = 0;
      status = tunnel_api->create_tunnel_map_entry(&tunnel_map_entry_oid, gSwitchId, attr_size, attr_list);
      sai_thrift_free_attr(attr_list);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return tunnel_map_entry_oid; }

      SAI_THRIFT_LOG_ERR("Failed to create OID.");

      return SAI_NULL_OBJECT_ID;
  }

  sai_thrift_status_t sai_thrift_remove_tunnel_map_entry(const sai_thrift_object_id_t tunnel_map_entry_id)
  {
      sai_tunnel_api_t *tunnel_api = nullptr;
      sai_status_t status;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_TUNNEL, (void **) &tunnel_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain tunnel_api, status:%d", status);
          return status;
      }

      return tunnel_api->remove_tunnel_map_entry((sai_object_id_t) tunnel_map_entry_id);
  }

  sai_thrift_status_t sai_thrift_set_tunnel_map_entry_attribute(const sai_thrift_object_id_t tunnel_map_entry_id,
                                                           const sai_thrift_attribute_t& thrift_attr)
  {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_tunnel_api_t *tunnel_api = nullptr;
      sai_attribute_t attr;
      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_TUNNEL, (void **) &tunnel_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain tunnel_api, status:%d", status);
          return status;
      }

      sai_thrift_parse_tunnel_map_entry_attributes(thrift_attr_list, &attr);

      return tunnel_api->set_tunnel_map_entry_attribute(tunnel_map_entry_id, &attr);
  }

  void sai_thrift_get_tunnel_map_entry_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t tunnel_map_entry_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_tunnel_api_t *tunnel_api = nullptr;
      uint32_t attr_count = 0;
      sai_attribute_t attr[14];
	  sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_TUNNEL, (void **) &tunnel_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain tunnel_api, status:%d", status);
          return;
      }

      attr[0].id = SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE;
      attr[1].id = SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP;
	  attr[2].id = SAI_TUNNEL_MAP_ENTRY_ATTR_OECN_KEY;
	  attr[3].id = SAI_TUNNEL_MAP_ENTRY_ATTR_OECN_VALUE;
	  attr[4].id = SAI_TUNNEL_MAP_ENTRY_ATTR_UECN_KEY;
	  attr[5].id = SAI_TUNNEL_MAP_ENTRY_ATTR_UECN_VALUE;
	  attr[6].id = SAI_TUNNEL_MAP_ENTRY_ATTR_VLAN_ID_KEY;
	  attr[7].id = SAI_TUNNEL_MAP_ENTRY_ATTR_VLAN_ID_VALUE;
	  attr[8].id = SAI_TUNNEL_MAP_ENTRY_ATTR_VNI_ID_KEY;
	  attr[9].id = SAI_TUNNEL_MAP_ENTRY_ATTR_VNI_ID_VALUE;
	  attr[10].id = SAI_TUNNEL_MAP_ENTRY_ATTR_BRIDGE_ID_KEY;
	  attr[11].id = SAI_TUNNEL_MAP_ENTRY_ATTR_BRIDGE_ID_VALUE;
	  attr[12].id = SAI_TUNNEL_MAP_ENTRY_ATTR_VIRTUAL_ROUTER_ID_KEY;
	  attr[13].id = SAI_TUNNEL_MAP_ENTRY_ATTR_VIRTUAL_ROUTER_ID_VALUE;
      attr_count = 14;

      status = tunnel_api->get_tunnel_map_entry_attribute(tunnel_map_entry_id, attr_count, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain tunnel map entry type, status:%d", status);
          return;
      }

	  thrift_attr.id = attr[0].id;
	  thrift_attr.value.s32 = attr[0].value.s32;
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[1].id;
	  thrift_attr.value.oid = attr[1].value.oid;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[2].id;
	  thrift_attr.value.u8 = attr[2].value.u8;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[3].id;
	  thrift_attr.value.u8 = attr[3].value.u8;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[4].id;
	  thrift_attr.value.u8 = attr[4].value.u8;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[5].id;
	  thrift_attr.value.u8 = attr[5].value.u8;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[6].id;
	  thrift_attr.value.u16 = attr[6].value.u16;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[7].id;
	  thrift_attr.value.u16 = attr[7].value.u16;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[8].id;
	  thrift_attr.value.u32 = attr[8].value.u32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[9].id;
	  thrift_attr.value.u32 = attr[9].value.u32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[10].id;
	  thrift_attr.value.oid = attr[10].value.oid;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[11].id;
	  thrift_attr.value.oid = attr[11].value.oid;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[12].id;
	  thrift_attr.value.oid = attr[12].value.oid;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
	  thrift_attr.id = attr[13].id;
	  thrift_attr.value.oid = attr[13].value.oid;
	  thrift_attr_list.attr_list.push_back(thrift_attr);
  }

  sai_thrift_object_id_t sai_thrift_create_tunnel_map(const std::vector<sai_thrift_attribute_t> &thrift_attr_list) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_tunnel_api_t *tunnel_api = nullptr;
      auto status = sai_api_query(SAI_API_TUNNEL, reinterpret_cast<void**>(&tunnel_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return SAI_NULL_OBJECT_ID; }

      sai_attribute_t *attr_list = nullptr;
      sai_size_t attr_size = thrift_attr_list.size();
      sai_thrift_alloc_attr(attr_list, attr_size);
      sai_thrift_parse_tunnel_map_attributes(thrift_attr_list, attr_list);

      sai_object_id_t tunnel_map_oid = 0;
      status = tunnel_api->create_tunnel_map(&tunnel_map_oid, gSwitchId, attr_size, attr_list);
      sai_thrift_free_attr(attr_list);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return tunnel_map_oid; }

      SAI_THRIFT_LOG_ERR("Failed to create OID.");

      return SAI_NULL_OBJECT_ID;
  }

  sai_thrift_status_t sai_thrift_remove_tunnel_map(const sai_thrift_object_id_t tunnel_map_id)
  {
      sai_tunnel_api_t *tunnel_api = nullptr;
      sai_status_t status;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_TUNNEL, (void **) &tunnel_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain tunnel_api, status:%d", status);
          return status;
      }

      return tunnel_api->remove_tunnel_map((sai_object_id_t) tunnel_map_id);
  }

  sai_thrift_status_t sai_thrift_set_tunnel_map_attribute(const sai_thrift_object_id_t tunnel_map_id,
                                                           const sai_thrift_attribute_t& thrift_attr)
  {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_tunnel_api_t *tunnel_api = nullptr;
      sai_attribute_t attr;
      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_TUNNEL, (void **) &tunnel_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain tunnel_api, status:%d", status);
          return status;
      }

      sai_thrift_parse_tunnel_map_attributes(thrift_attr_list, &attr);

      return tunnel_api->set_tunnel_map_attribute(tunnel_map_id, &attr);
  }

  void sai_thrift_get_tunnel_map_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t tunnel_map_id) {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_tunnel_api_t *tunnel_api = nullptr;
      uint32_t attr_count = 0;
      sai_attribute_t attr[2];
	  sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_TUNNEL, (void **) &tunnel_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain tunnel_api, status:%d", status);
          return;
      }

      attr[0].id = SAI_TUNNEL_MAP_ATTR_TYPE;
	  attr[1].id = SAI_TUNNEL_MAP_ATTR_ENTRY_LIST;
	  attr[1].value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * 128);
      attr[1].value.objlist.count = 128;
      attr_count = 2;

      status = tunnel_api->get_tunnel_map_attribute(tunnel_map_id, attr_count, attr);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain tunnel map type, status:%d", status);
          return;
      }

	  thrift_attr.id = attr[0].id;
	  thrift_attr.value.s32 = attr[0].value.s32;
      thrift_attr_list.attr_list.push_back(thrift_attr);
      thrift_attr.id = attr[1].id;
	  thrift_attr.value.objlist.count = attr[1].value.objlist.count;
	  sai_object_list_t *map_entry_list_object;
	  std::vector<sai_thrift_object_id_t>& map_entry_list = thrift_attr.value.objlist.object_id_list;
      map_entry_list_object = &attr[1].value.objlist;
      for (int index = 0; index < attr[1].value.objlist.count; index++) {
          map_entry_list.push_back((sai_thrift_object_id_t) map_entry_list_object->list[index]);
      }
      thrift_attr_list.attr_list.push_back(thrift_attr);
	  free(attr[1].value.objlist.list);
  }

  sai_thrift_object_id_t sai_thrift_create_tunnel(const std::vector<sai_thrift_attribute_t> &thrift_attr_list) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_tunnel_api_t *tunnel_api = nullptr;
	  sai_object_id_t *mapper_list = NULL;
      auto status = sai_api_query(SAI_API_TUNNEL, reinterpret_cast<void**>(&tunnel_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return SAI_NULL_OBJECT_ID; }

      sai_attribute_t *attr_list = nullptr;
      sai_size_t attr_size = thrift_attr_list.size();
      sai_thrift_alloc_attr(attr_list, attr_size);
      sai_thrift_parse_tunnel_attributes(thrift_attr_list, attr_list, &mapper_list);

      sai_object_id_t tunnel_oid = 0;
      status = tunnel_api->create_tunnel(&tunnel_oid, gSwitchId, attr_size, attr_list);
      sai_thrift_free_attr(attr_list);

      if (mapper_list) free(mapper_list);
      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return tunnel_oid; }

      SAI_THRIFT_LOG_ERR("Failed to create OID.");

      return SAI_NULL_OBJECT_ID;
  }

  sai_thrift_status_t sai_thrift_remove_tunnel(const sai_thrift_object_id_t tunnel_id)
  {
      sai_tunnel_api_t *tunnel_api = nullptr;
      sai_status_t status;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_TUNNEL, (void **) &tunnel_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain tunnel_api, status:%d", status);
          return status;
      }

      return tunnel_api->remove_tunnel((sai_object_id_t) tunnel_id);
  }

  sai_thrift_status_t sai_thrift_set_tunnel_attribute(const sai_thrift_object_id_t tunnel_id,
                                                           const sai_thrift_attribute_t& thrift_attr)
  {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_tunnel_api_t *tunnel_api = nullptr;
      sai_attribute_t attr;
      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };
	  sai_object_id_t *mapper_list = NULL;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_TUNNEL, (void **) &tunnel_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain tunnel_api, status:%d", status);
          return status;
      }

      sai_thrift_parse_tunnel_attributes(thrift_attr_list, &attr, &mapper_list);
	  if (mapper_list) free(mapper_list);
      status = tunnel_api->set_tunnel_attribute(tunnel_id, &attr);

	  return status;
  }

  void sai_thrift_get_tunnel_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t tunnel_id,
  	                                       const std::vector < int32_t > & thrift_attr_ids) {
	sai_status_t status = SAI_STATUS_SUCCESS;
	sai_tunnel_api_t *tunnel_api = nullptr;
	sai_thrift_attribute_t thrift_attr;

	SAI_THRIFT_FUNC_LOG();

	thrift_attr_list.attr_count = 0;

	status = sai_api_query(SAI_API_TUNNEL, (void **) &tunnel_api);
	if (status != SAI_STATUS_SUCCESS) {
		SAI_THRIFT_LOG_ERR("failed to obtain tunnel_api, status:%d", status);
		return;
	}

	uint32_t attr_count = thrift_attr_ids.size();
	sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_ids.size());
	memset(attr_list, 0x0, sizeof(sizeof(sai_attribute_t) * thrift_attr_ids.size()));
	sai_thrift_parse_attribute_ids(thrift_attr_ids, attr_list);

	for (uint32_t i = 0; i < attr_count; i++)
	{
		switch(attr_list[i].id)
		{
			case SAI_TUNNEL_ATTR_TYPE:
			case SAI_TUNNEL_ATTR_ENCAP_TTL_MODE:
			case SAI_TUNNEL_ATTR_ENCAP_DSCP_MODE:
			case SAI_TUNNEL_ATTR_ENCAP_ECN_MODE:
			case SAI_TUNNEL_ATTR_DECAP_ECN_MODE:
			case SAI_TUNNEL_ATTR_DECAP_TTL_MODE:
			case SAI_TUNNEL_ATTR_DECAP_DSCP_MODE:
			case SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE:
			case SAI_TUNNEL_ATTR_OVERLAY_INTERFACE:
			case SAI_TUNNEL_ATTR_ENCAP_SRC_IP:
			case SAI_TUNNEL_ATTR_ENCAP_TTL_VAL:
			case SAI_TUNNEL_ATTR_ENCAP_DSCP_VAL:
			case SAI_TUNNEL_ATTR_ENCAP_GRE_KEY_VALID:
			case SAI_TUNNEL_ATTR_ENCAP_GRE_KEY:
				break;
			case SAI_TUNNEL_ATTR_ENCAP_MAPPERS:
			case SAI_TUNNEL_ATTR_DECAP_MAPPERS:
			case SAI_TUNNEL_ATTR_TERM_TABLE_ENTRY_LIST:
				attr_list[i].value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * CNT_UNSUPPORT);
				attr_list[i].value.objlist.count = CNT_UNSUPPORT;
				break;
		   default:
				return;
		}
	}

	status = tunnel_api->get_tunnel_attribute(tunnel_id, attr_count, attr_list);
	if (status != SAI_STATUS_SUCCESS) {
		SAI_THRIFT_LOG_ERR("failed to obtain tunnel type, status:%d", status);
		return;
	}

	for (uint32_t i = 0; i < attr_count; i++)
	{
		switch(attr_list[i].id)
		{
			case SAI_TUNNEL_ATTR_TYPE:
			case SAI_TUNNEL_ATTR_ENCAP_TTL_MODE:
			case SAI_TUNNEL_ATTR_ENCAP_DSCP_MODE:
			case SAI_TUNNEL_ATTR_ENCAP_ECN_MODE:
			case SAI_TUNNEL_ATTR_DECAP_ECN_MODE:
			case SAI_TUNNEL_ATTR_DECAP_TTL_MODE:
			case SAI_TUNNEL_ATTR_DECAP_DSCP_MODE:
                thrift_attr.id        = attr_list[i].id;
                thrift_attr.value.s32 = attr_list[i].value.s32;
                thrift_attr_list.attr_list.push_back(thrift_attr);
				break;
			case SAI_TUNNEL_ATTR_UNDERLAY_INTERFACE:
			case SAI_TUNNEL_ATTR_OVERLAY_INTERFACE:
				thrift_attr.id        = attr_list[i].id;
                thrift_attr.value.oid = attr_list[i].value.oid;
                thrift_attr_list.attr_list.push_back(thrift_attr);
				break;
			case SAI_TUNNEL_ATTR_ENCAP_SRC_IP:
  		  	    thrift_attr.id        = attr_list[i].id;
				thrift_attr.value.ipaddr.addr_family = attr_list[i].value.ipaddr.addr_family;
  		        if (SAI_IP_ADDR_FAMILY_IPV4 == attr_list[i].value.ipaddr.addr_family)
  		        {
  		          thrift_attr.value.ipaddr.addr.ip4 = sai_thrift_v4_ip_to_string(attr_list[i].value.ipaddr.addr.ip4);
  		        }
  		        else
  		        {
  		          //thrift_attr.value.ipaddr.addr.ip6 = sai_thrift_v4_ip_to_string(attr[i].value.ipaddr.addr.ip4);
  		        }
  		        thrift_attr_list.attr_list.push_back(thrift_attr);
				break;
			case SAI_TUNNEL_ATTR_ENCAP_TTL_VAL:
			case SAI_TUNNEL_ATTR_ENCAP_DSCP_VAL:
				thrift_attr.id        = attr_list[i].id;
                thrift_attr.value.u8 = attr_list[i].value.u8;
                thrift_attr_list.attr_list.push_back(thrift_attr);
				break;
			case SAI_TUNNEL_ATTR_ENCAP_GRE_KEY_VALID:
				thrift_attr.id        = attr_list[i].id;
                thrift_attr.value.booldata = attr_list[i].value.booldata;
                thrift_attr_list.attr_list.push_back(thrift_attr);
				break;
			case SAI_TUNNEL_ATTR_ENCAP_GRE_KEY:
				thrift_attr.id        = attr_list[i].id;
                thrift_attr.value.u32 = attr_list[i].value.u32;
                thrift_attr_list.attr_list.push_back(thrift_attr);
				break;
			case SAI_TUNNEL_ATTR_ENCAP_MAPPERS:
			case SAI_TUNNEL_ATTR_DECAP_MAPPERS:
			case SAI_TUNNEL_ATTR_TERM_TABLE_ENTRY_LIST:
			    {
					sai_object_list_t *map_entry_list_object;
					thrift_attr.id = attr_list[i].id;
					thrift_attr.value.objlist.count = attr_list[i].value.objlist.count;
					std::vector<sai_thrift_object_id_t>& map_entry_list = thrift_attr.value.objlist.object_id_list;
					map_entry_list_object = &attr_list[i].value.objlist;
					for (int index = 0; index < attr_list[i].value.objlist.count; index++) {
					  map_entry_list.push_back((sai_thrift_object_id_t) map_entry_list_object->list[index]);
					}
					thrift_attr_list.attr_list.push_back(thrift_attr);
					free(attr_list[i].value.objlist.list);
				}
				break;
			default:
				SAI_THRIFT_LOG_ERR("Failed to parse attribute.");
				break;
          }
      }

 	  if(attr_list)
 	  {
 	      free(attr_list);
 	  }
	  return;
  }
  void sai_thrift_get_tunnel_stats(std::vector<int64_t> & thrift_counters,
                                  const sai_thrift_object_id_t tunnel_id,
                                  const std::vector<sai_thrift_queue_stat_counter_t> & thrift_counter_ids,
                                  const int32_t number_of_counters) {
      printf("sai_thrift_get_tunnel_stats\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_tunnel_api_t *tunnel_api = nullptr;
      status = sai_api_query(SAI_API_TUNNEL, (void **) &tunnel_api);
      if (status != SAI_STATUS_SUCCESS) {
          return;
      }
      sai_stat_id_t *counter_ids = (sai_stat_id_t *) malloc(sizeof(sai_tunnel_stat_t) * thrift_counter_ids.size());
      std::vector<int32_t>::const_iterator it = thrift_counter_ids.begin();
      uint64_t *counters = (uint64_t *) malloc(sizeof(uint64_t) * thrift_counter_ids.size());
      for(uint32_t i = 0; i < thrift_counter_ids.size(); i++, it++) {
          counter_ids[i] = (sai_tunnel_stat_t) *it;
      }

      status = tunnel_api->get_tunnel_stats(
                             (sai_object_id_t) tunnel_id,
                             number_of_counters,
                             counter_ids,
                             counters);

      for (uint32_t i = 0; i < thrift_counter_ids.size(); i++) {
          thrift_counters.push_back(counters[i]);
      }
      free(counter_ids);
      free(counters);
      return;
   }

  sai_thrift_status_t sai_thrift_clear_tunnel_stats(const sai_thrift_object_id_t queue_id,
                                                   const std::vector<sai_thrift_queue_stat_counter_t> & thrift_counter_ids,
                                                   const int32_t number_of_counters) {
      printf("sai_thrift_clear_queue_stats\n");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_tunnel_api_t *tunnel_api=nullptr;
      status = sai_api_query(SAI_API_TUNNEL, (void **) &tunnel_api);
      if (status != SAI_STATUS_SUCCESS) {
          return status;
      }
      sai_stat_id_t *counter_ids = (sai_stat_id_t *) malloc(sizeof(sai_tunnel_stat_t) * thrift_counter_ids.size());
      std::vector<int32_t>::const_iterator it = thrift_counter_ids.begin();
      for(uint32_t i = 0; i < thrift_counter_ids.size(); i++, it++) {
          counter_ids[i] = (sai_tunnel_stat_t) *it;
      }

      status = tunnel_api->clear_tunnel_stats(
                             (sai_object_id_t) queue_id,
                             number_of_counters,
                             counter_ids);

      free(counter_ids);
      return status;
  }

  sai_thrift_object_id_t sai_thrift_create_tunnel_term_table_entry(const std::vector<sai_thrift_attribute_t> &thrift_attr_list) noexcept
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_tunnel_api_t *tunnel_api = nullptr;
      auto status = sai_api_query(SAI_API_TUNNEL, reinterpret_cast<void**>(&tunnel_api));

      if (status != SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_ERR("Failed to get API."); return SAI_NULL_OBJECT_ID; }

      sai_attribute_t *attr_list = nullptr;
      sai_size_t attr_size = thrift_attr_list.size();
      sai_thrift_alloc_attr(attr_list, attr_size);
      sai_thrift_parse_tunnel_term_table_entry_attributes(thrift_attr_list, attr_list);

      sai_object_id_t tunnel_term_table_entry_oid = 0;
      status = tunnel_api->create_tunnel_term_table_entry(&tunnel_term_table_entry_oid, gSwitchId, attr_size, attr_list);
      sai_thrift_free_attr(attr_list);

      if (status == SAI_STATUS_SUCCESS)
      { SAI_THRIFT_LOG_DBG("Exited."); return tunnel_term_table_entry_oid; }

      SAI_THRIFT_LOG_ERR("Failed to create OID.");

      return SAI_NULL_OBJECT_ID;
  }

  sai_thrift_status_t sai_thrift_remove_tunnel_term_table_entry(const sai_thrift_object_id_t tunnel_term_table_entry_id)
  {
      sai_tunnel_api_t *tunnel_api = nullptr;
      sai_status_t status;

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_TUNNEL, (void **) &tunnel_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain tunnel_api, status:%d", status);
          return status;
      }

      return tunnel_api->remove_tunnel_term_table_entry((sai_object_id_t) tunnel_term_table_entry_id);
  }

  sai_thrift_status_t sai_thrift_set_tunnel_term_table_entry_attribute(const sai_thrift_object_id_t tunnel_term_table_entry_id,
                                                           const sai_thrift_attribute_t& thrift_attr)
  {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_tunnel_api_t *tunnel_api = nullptr;
      sai_attribute_t attr;
      const std::vector<sai_thrift_attribute_t> thrift_attr_list = { thrift_attr };

      SAI_THRIFT_FUNC_LOG();

      status = sai_api_query(SAI_API_TUNNEL, (void **) &tunnel_api);
      if (status != SAI_STATUS_SUCCESS) {
          SAI_THRIFT_LOG_ERR("failed to obtain tunnel_api, status:%d", status);
          return status;
      }

      sai_thrift_parse_tunnel_term_table_entry_attributes(thrift_attr_list, &attr);

      return tunnel_api->set_tunnel_term_table_entry_attribute(tunnel_term_table_entry_id, &attr);
  }

  void sai_thrift_get_tunnel_term_table_entry_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t tunnel_term_table_entry_id,
  	                                                            const std::vector < int32_t > & thrift_attr_ids) {
	sai_status_t status = SAI_STATUS_SUCCESS;
	sai_tunnel_api_t *tunnel_api = nullptr;
	sai_thrift_attribute_t thrift_attr;

	SAI_THRIFT_FUNC_LOG();

	thrift_attr_list.attr_count = 0;

	status = sai_api_query(SAI_API_TUNNEL, (void **) &tunnel_api);
	if (status != SAI_STATUS_SUCCESS) {
		SAI_THRIFT_LOG_ERR("failed to obtain tunnel_api, status:%d", status);
		return;
	}

	uint32_t attr_count = thrift_attr_ids.size();
	sai_attribute_t *attr_list = (sai_attribute_t *) malloc(sizeof(sai_attribute_t) * thrift_attr_ids.size());
	memset(attr_list, 0x0, sizeof(sizeof(sai_attribute_t) * thrift_attr_ids.size()));
	sai_thrift_parse_attribute_ids(thrift_attr_ids, attr_list);

	for (uint32_t i = 0; i < attr_count; i++)
	{
		switch(attr_list[i].id)
		{
			  case SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_TYPE:
			  case SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_TUNNEL_TYPE:
		      case SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_VR_ID:
		      case SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_ACTION_TUNNEL_ID:
			  case SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_DST_IP:
			  case SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_SRC_IP:
			  	  break;
			  default:
				return;
		}
	}

	status = tunnel_api->get_tunnel_term_table_entry_attribute(tunnel_term_table_entry_id, attr_count, attr_list);
	if (status != SAI_STATUS_SUCCESS) {
		SAI_THRIFT_LOG_ERR("failed to obtain tunnel term table entry attr, status:%d", status);
		return;
	}

	for (uint32_t i = 0; i < attr_count; i++)
	{
		switch(attr_list[i].id)
		{
			  case SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_TYPE:
			  case SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_TUNNEL_TYPE:
                  thrift_attr.id        = attr_list[i].id;
                  thrift_attr.value.s32 = attr_list[i].value.s32;
                  thrift_attr_list.attr_list.push_back(thrift_attr);
				  break;
		      case SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_VR_ID:
		      case SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_ACTION_TUNNEL_ID:
  				  thrift_attr.id        = attr_list[i].id;
                  thrift_attr.value.oid = attr_list[i].value.oid;
                  thrift_attr_list.attr_list.push_back(thrift_attr);
			  	  break;
			  case SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_DST_IP:
			  case SAI_TUNNEL_TERM_TABLE_ENTRY_ATTR_SRC_IP:
			  	  thrift_attr.id        = attr_list[i].id;
				  thrift_attr.value.ipaddr.addr_family = attr_list[i].value.ipaddr.addr_family;
  		          if (SAI_IP_ADDR_FAMILY_IPV4 == attr_list[i].value.ipaddr.addr_family)
  		          {
  		            thrift_attr.value.ipaddr.addr.ip4 = sai_thrift_v4_ip_to_string(attr_list[i].value.ipaddr.addr.ip4);
  		          }
  		          else
  		          {
  		            //thrift_attr.value.ipaddr.addr.ip6 = sai_thrift_v4_ip_to_string(attr[i].value.ipaddr.addr.ip4);
  		          }
  		          thrift_attr_list.attr_list.push_back(thrift_attr);

			  	  break;
			default:
				SAI_THRIFT_LOG_ERR("Failed to parse attribute.");
				break;
          }
      }

 	  if(attr_list)
 	  {
 	      free(attr_list);
 	  }
	  return;
  }
  void sai_thrift_get_cpu_packet_attribute(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t switch_id) {
	  sai_thrift_attribute_t thrift_attr;
	  uint32_t index = 0;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;
	  for (index = 0; index< packet_rx_attr_count; index++)
	  {
		  thrift_attr.id = packet_rx_attr[index].id;
		  thrift_attr.value.oid = packet_rx_attr[index].value.oid;
	      thrift_attr_list.attr_list.push_back(thrift_attr);
	  }
  }

  void sai_thrift_get_cpu_packet_count(sai_thrift_result_t &ret) {
	  uint32_t index = 0;

      SAI_THRIFT_FUNC_LOG();

      ret.data.u16 = packets_rx_count;
	  ret.status = SAI_STATUS_SUCCESS;
  }
  void sai_thrift_clear_cpu_packet_info(sai_thrift_result_t &ret) {
	  sai_thrift_attribute_t thrift_attr;
	  uint32_t index = 0;

      SAI_THRIFT_FUNC_LOG();

	  packets_rx_count = 0;
	  memset(&packet_rx_attr, 0, sizeof(packet_rx_attr));

	  ret.status = SAI_STATUS_SUCCESS;
  }

  sai_thrift_status_t sai_thrift_log_set(const int32_t sai_api_id,  const int32_t  log_level) {

      SAI_THRIFT_FUNC_LOG();
	  return sai_log_set((sai_api_t)sai_api_id, (sai_log_level_t)log_level);
  }



  sai_thrift_object_id_t sai_thrift_create_isolation_group(const std_sai_thrift_attr_vctr_t &thrift_attr_list)
  {
      SAI_THRIFT_LOG_DBG("Called.");

      sai_isolation_group_api_t *isolation_group_api = nullptr;
      auto status = sai_api_query(SAI_API_ISOLATION_GROUP, reinterpret_cast < void** > (&isolation_group_api));

      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("Failed to get isolation group API.");
          return SAI_NULL_OBJECT_ID;
      }

      sai_attribute_t *attr_list = nullptr;
      sai_uint32_t attr_size = thrift_attr_list.size();
      sai_thrift_alloc_attr(attr_list, attr_size);
      sai_thrift_parse_isolation_group_attributes(thrift_attr_list, attr_list);

      sai_object_id_t isolation_group_oid = 0;
      status = isolation_group_api->create_isolation_group(&isolation_group_oid, gSwitchId, attr_size, attr_list);
      sai_thrift_free_attr(attr_list);

      if (status == SAI_STATUS_SUCCESS)
      {
          return isolation_group_oid;
      }

      SAI_THRIFT_LOG_ERR("Failed to create isolation group.");

      return SAI_NULL_OBJECT_ID;
  }

  sai_thrift_status_t sai_thrift_remove_isolation_group(const sai_thrift_object_id_t iso_group_oid)
  {
      SAI_THRIFT_LOG_DBG("Called.");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_isolation_group_api_t *isolation_group_api = nullptr;
      status = sai_api_query(SAI_API_ISOLATION_GROUP, reinterpret_cast < void** > (&isolation_group_api));
      if (status != SAI_STATUS_SUCCESS)
      {
          return status;
      }
      status = isolation_group_api->remove_isolation_group(iso_group_oid);
      return status;
  }

  sai_thrift_object_id_t sai_thrift_create_isolation_group_member(const std_sai_thrift_attr_vctr_t &thrift_attr_list)
  {
      SAI_THRIFT_LOG_DBG("Called.");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_isolation_group_api_t *isolation_group_api = nullptr;
      status = sai_api_query(SAI_API_ISOLATION_GROUP, reinterpret_cast < void** > (&isolation_group_api));
      if (status != SAI_STATUS_SUCCESS)
      {
          return status;
      }
      sai_attribute_t *attr_list = nullptr;
      sai_uint32_t attr_size = thrift_attr_list.size();
      sai_thrift_alloc_attr(attr_list, attr_size);
      sai_thrift_parse_isolation_group_member_attributes(thrift_attr_list, attr_list);
      sai_object_id_t isolation_group_member_oid = 0;
      status = isolation_group_api->create_isolation_group_member(&isolation_group_member_oid, gSwitchId, attr_size, attr_list);
      sai_thrift_free_attr(attr_list);

      if (status == SAI_STATUS_SUCCESS)
      {
          return isolation_group_member_oid;
      }
      SAI_THRIFT_LOG_ERR("Failed to create isolation group.");

      return SAI_NULL_OBJECT_ID;
  }

  sai_thrift_status_t sai_thrift_remove_isolation_group_member(const sai_thrift_object_id_t member_oid)
  {
      SAI_THRIFT_LOG_DBG("Called.");
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_isolation_group_api_t *isolation_group_api = nullptr;
      status = sai_api_query(SAI_API_ISOLATION_GROUP, reinterpret_cast < void** > (&isolation_group_api));
      if (status != SAI_STATUS_SUCCESS)
      {
          return status;
      }
      status = isolation_group_api->remove_isolation_group_member(member_oid);
      return status;
  }

  void sai_thrift_get_isolation_group_attributes(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t iso_group_oid)
  {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_isolation_group_api_t *iso_group_api;
      sai_attribute_t attr[2];
	  sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_ISOLATION_GROUP, (void **) &iso_group_api);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("failed to obtain ISOLATION_GROUP api, status:%d", status);
          return;
      }

      attr[0].id = SAI_ISOLATION_GROUP_ATTR_TYPE;
      attr[1].id = SAI_ISOLATION_GROUP_ATTR_ISOLATION_MEMBER_LIST;
	  attr[1].value.objlist.list = (sai_object_id_t *) malloc(sizeof(sai_object_id_t) * 128);

      status = iso_group_api->get_isolation_group_attribute(iso_group_oid, 2, attr);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("failed to obtain vlan member attributes, status:%d", status);
          return;
      }
	  thrift_attr.id = SAI_ISOLATION_GROUP_ATTR_TYPE;
	  thrift_attr.value.u32 = attr[0].value.u32;
	  thrift_attr_list.attr_list.push_back(thrift_attr);

	  thrift_attr.id = SAI_ISOLATION_GROUP_ATTR_ISOLATION_MEMBER_LIST;
	  thrift_attr.value.objlist.count = attr[1].value.objlist.count;
	  std::vector < sai_thrift_object_id_t > & iso_grp_member_list = thrift_attr.value.objlist.object_id_list;
	  for (int index = 0; index < attr[1].value.objlist.count; index++) {
          iso_grp_member_list.push_back((sai_thrift_object_id_t) attr[1].value.objlist.list[index]);
      }
	  thrift_attr_list.attr_list.push_back(thrift_attr);

	free(attr[1].value.objlist.list);
  }

  void sai_thrift_get_isolation_group_member_attributes(sai_thrift_attribute_list_t& thrift_attr_list, const sai_thrift_object_id_t member_oid)
  {
      sai_status_t status = SAI_STATUS_SUCCESS;
      sai_isolation_group_api_t *iso_group_api;
      sai_attribute_t attr[2];
      sai_thrift_attribute_t thrift_attr;

      SAI_THRIFT_FUNC_LOG();

      thrift_attr_list.attr_count = 0;

      status = sai_api_query(SAI_API_ISOLATION_GROUP, (void **) &iso_group_api);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("failed to obtain ISOLATION_GROUP api, status:%d", status);
          return;
      }

      attr[0].id = SAI_ISOLATION_GROUP_MEMBER_ATTR_ISOLATION_GROUP_ID;
      attr[1].id = SAI_ISOLATION_GROUP_MEMBER_ATTR_ISOLATION_OBJECT;

      status = iso_group_api->get_isolation_group_member_attribute(member_oid, 2, attr);
      if (status != SAI_STATUS_SUCCESS)
      {
          SAI_THRIFT_LOG_ERR("failed to obtain vlan member attributes, status:%d", status);
          return;
      }
      thrift_attr.id = SAI_ISOLATION_GROUP_MEMBER_ATTR_ISOLATION_GROUP_ID;
      thrift_attr.value.oid = attr[0].value.oid;
      thrift_attr_list.attr_list.push_back(thrift_attr);

      thrift_attr.id = SAI_ISOLATION_GROUP_MEMBER_ATTR_ISOLATION_OBJECT;
	  thrift_attr.value.oid = attr[1].value.oid;

      thrift_attr_list.attr_list.push_back(thrift_attr);

  }

};

static void * switch_sai_thrift_rpc_server_thread(void *arg) {
  int port = *(int *) arg;
  shared_ptr<switch_sai_rpcHandler> handler(new switch_sai_rpcHandler());
  shared_ptr<TProcessor> processor(new switch_sai_rpcProcessor(handler));
  shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
  shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
  shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());

  TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
  server.serve();
  return 0;
}

static pthread_t switch_sai_thrift_rpc_thread;

extern "C" {

int start_sai_thrift_rpc_server(int port)
{
    static int param = port;

    std::cerr << "Starting SAI RPC server on port " << port << std::endl;

    int rc = pthread_create(&switch_sai_thrift_rpc_thread, NULL, switch_sai_thrift_rpc_server_thread, &param);
    std::cerr << "create pthread switch_sai_thrift_rpc_server_thread result " << rc << std::endl;

    rc = pthread_detach(switch_sai_thrift_rpc_thread);
    std::cerr << "detach switch_sai_thrift_rpc_server_thread rc" << rc  << std::endl;

    return rc;
}
}
